diff --git a/api/connect/marketmap/v2/tx.pulsar.go b/api/connect/marketmap/v2/tx.pulsar.go index 093ac59f4..8f48f9f99 100644 --- a/api/connect/marketmap/v2/tx.pulsar.go +++ b/api/connect/marketmap/v2/tx.pulsar.go @@ -4809,6 +4809,1030 @@ func (x *fastReflection_MsgRemoveMarketAuthoritiesResponse) ProtoMethods() *prot } } +var _ protoreflect.List = (*_MsgRemoveMarkets_2_list)(nil) + +type _MsgRemoveMarkets_2_list struct { + list *[]string +} + +func (x *_MsgRemoveMarkets_2_list) Len() int { + if x.list == nil { + return 0 + } + return len(*x.list) +} + +func (x *_MsgRemoveMarkets_2_list) Get(i int) protoreflect.Value { + return protoreflect.ValueOfString((*x.list)[i]) +} + +func (x *_MsgRemoveMarkets_2_list) Set(i int, value protoreflect.Value) { + valueUnwrapped := value.String() + concreteValue := valueUnwrapped + (*x.list)[i] = concreteValue +} + +func (x *_MsgRemoveMarkets_2_list) Append(value protoreflect.Value) { + valueUnwrapped := value.String() + concreteValue := valueUnwrapped + *x.list = append(*x.list, concreteValue) +} + +func (x *_MsgRemoveMarkets_2_list) AppendMutable() protoreflect.Value { + panic(fmt.Errorf("AppendMutable can not be called on message MsgRemoveMarkets at list field Markets as it is not of Message kind")) +} + +func (x *_MsgRemoveMarkets_2_list) Truncate(n int) { + *x.list = (*x.list)[:n] +} + +func (x *_MsgRemoveMarkets_2_list) NewElement() protoreflect.Value { + v := "" + return protoreflect.ValueOfString(v) +} + +func (x *_MsgRemoveMarkets_2_list) IsValid() bool { + return x.list != nil +} + +var ( + md_MsgRemoveMarkets protoreflect.MessageDescriptor + fd_MsgRemoveMarkets_admin protoreflect.FieldDescriptor + fd_MsgRemoveMarkets_markets protoreflect.FieldDescriptor +) + +func init() { + file_connect_marketmap_v2_tx_proto_init() + md_MsgRemoveMarkets = File_connect_marketmap_v2_tx_proto.Messages().ByName("MsgRemoveMarkets") + fd_MsgRemoveMarkets_admin = md_MsgRemoveMarkets.Fields().ByName("admin") + fd_MsgRemoveMarkets_markets = md_MsgRemoveMarkets.Fields().ByName("markets") +} + +var _ protoreflect.Message = (*fastReflection_MsgRemoveMarkets)(nil) + +type fastReflection_MsgRemoveMarkets MsgRemoveMarkets + +func (x *MsgRemoveMarkets) ProtoReflect() protoreflect.Message { + return (*fastReflection_MsgRemoveMarkets)(x) +} + +func (x *MsgRemoveMarkets) slowProtoReflect() protoreflect.Message { + mi := &file_connect_marketmap_v2_tx_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +var _fastReflection_MsgRemoveMarkets_messageType fastReflection_MsgRemoveMarkets_messageType +var _ protoreflect.MessageType = fastReflection_MsgRemoveMarkets_messageType{} + +type fastReflection_MsgRemoveMarkets_messageType struct{} + +func (x fastReflection_MsgRemoveMarkets_messageType) Zero() protoreflect.Message { + return (*fastReflection_MsgRemoveMarkets)(nil) +} +func (x fastReflection_MsgRemoveMarkets_messageType) New() protoreflect.Message { + return new(fastReflection_MsgRemoveMarkets) +} +func (x fastReflection_MsgRemoveMarkets_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_MsgRemoveMarkets +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_MsgRemoveMarkets) Descriptor() protoreflect.MessageDescriptor { + return md_MsgRemoveMarkets +} + +// Type returns the message type, which encapsulates both Go and protobuf +// type information. If the Go type information is not needed, +// it is recommended that the message descriptor be used instead. +func (x *fastReflection_MsgRemoveMarkets) Type() protoreflect.MessageType { + return _fastReflection_MsgRemoveMarkets_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_MsgRemoveMarkets) New() protoreflect.Message { + return new(fastReflection_MsgRemoveMarkets) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_MsgRemoveMarkets) Interface() protoreflect.ProtoMessage { + return (*MsgRemoveMarkets)(x) +} + +// Range iterates over every populated field in an undefined order, +// calling f for each field descriptor and value encountered. +// Range returns immediately if f returns false. +// While iterating, mutating operations may only be performed +// on the current field descriptor. +func (x *fastReflection_MsgRemoveMarkets) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { + if x.Admin != "" { + value := protoreflect.ValueOfString(x.Admin) + if !f(fd_MsgRemoveMarkets_admin, value) { + return + } + } + if len(x.Markets) != 0 { + value := protoreflect.ValueOfList(&_MsgRemoveMarkets_2_list{list: &x.Markets}) + if !f(fd_MsgRemoveMarkets_markets, value) { + return + } + } +} + +// Has reports whether a field is populated. +// +// Some fields have the property of nullability where it is possible to +// distinguish between the default value of a field and whether the field +// was explicitly populated with the default value. Singular message fields, +// member fields of a oneof, and proto2 scalar fields are nullable. Such +// fields are populated only if explicitly set. +// +// In other cases (aside from the nullable cases above), +// a proto3 scalar field is populated if it contains a non-zero value, and +// a repeated field is populated if it is non-empty. +func (x *fastReflection_MsgRemoveMarkets) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + case "connect.marketmap.v2.MsgRemoveMarkets.admin": + return x.Admin != "" + case "connect.marketmap.v2.MsgRemoveMarkets.markets": + return len(x.Markets) != 0 + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: connect.marketmap.v2.MsgRemoveMarkets")) + } + panic(fmt.Errorf("message connect.marketmap.v2.MsgRemoveMarkets does not contain field %s", fd.FullName())) + } +} + +// Clear clears the field such that a subsequent Has call reports false. +// +// Clearing an extension field clears both the extension type and value +// associated with the given field number. +// +// Clear is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_MsgRemoveMarkets) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + case "connect.marketmap.v2.MsgRemoveMarkets.admin": + x.Admin = "" + case "connect.marketmap.v2.MsgRemoveMarkets.markets": + x.Markets = nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: connect.marketmap.v2.MsgRemoveMarkets")) + } + panic(fmt.Errorf("message connect.marketmap.v2.MsgRemoveMarkets does not contain field %s", fd.FullName())) + } +} + +// Get retrieves the value for a field. +// +// For unpopulated scalars, it returns the default value, where +// the default value of a bytes scalar is guaranteed to be a copy. +// For unpopulated composite types, it returns an empty, read-only view +// of the value; to obtain a mutable reference, use Mutable. +func (x *fastReflection_MsgRemoveMarkets) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + case "connect.marketmap.v2.MsgRemoveMarkets.admin": + value := x.Admin + return protoreflect.ValueOfString(value) + case "connect.marketmap.v2.MsgRemoveMarkets.markets": + if len(x.Markets) == 0 { + return protoreflect.ValueOfList(&_MsgRemoveMarkets_2_list{}) + } + listValue := &_MsgRemoveMarkets_2_list{list: &x.Markets} + return protoreflect.ValueOfList(listValue) + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: connect.marketmap.v2.MsgRemoveMarkets")) + } + panic(fmt.Errorf("message connect.marketmap.v2.MsgRemoveMarkets does not contain field %s", descriptor.FullName())) + } +} + +// Set stores the value for a field. +// +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType. +// When setting a composite type, it is unspecified whether the stored value +// aliases the source's memory in any way. If the composite value is an +// empty, read-only value, then it panics. +// +// Set is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_MsgRemoveMarkets) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + case "connect.marketmap.v2.MsgRemoveMarkets.admin": + x.Admin = value.Interface().(string) + case "connect.marketmap.v2.MsgRemoveMarkets.markets": + lv := value.List() + clv := lv.(*_MsgRemoveMarkets_2_list) + x.Markets = *clv.list + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: connect.marketmap.v2.MsgRemoveMarkets")) + } + panic(fmt.Errorf("message connect.marketmap.v2.MsgRemoveMarkets does not contain field %s", fd.FullName())) + } +} + +// Mutable returns a mutable reference to a composite type. +// +// If the field is unpopulated, it may allocate a composite value. +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType +// if not already stored. +// It panics if the field does not contain a composite type. +// +// Mutable is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_MsgRemoveMarkets) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "connect.marketmap.v2.MsgRemoveMarkets.markets": + if x.Markets == nil { + x.Markets = []string{} + } + value := &_MsgRemoveMarkets_2_list{list: &x.Markets} + return protoreflect.ValueOfList(value) + case "connect.marketmap.v2.MsgRemoveMarkets.admin": + panic(fmt.Errorf("field admin of message connect.marketmap.v2.MsgRemoveMarkets is not mutable")) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: connect.marketmap.v2.MsgRemoveMarkets")) + } + panic(fmt.Errorf("message connect.marketmap.v2.MsgRemoveMarkets does not contain field %s", fd.FullName())) + } +} + +// NewField returns a new value that is assignable to the field +// for the given descriptor. For scalars, this returns the default value. +// For lists, maps, and messages, this returns a new, empty, mutable value. +func (x *fastReflection_MsgRemoveMarkets) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "connect.marketmap.v2.MsgRemoveMarkets.admin": + return protoreflect.ValueOfString("") + case "connect.marketmap.v2.MsgRemoveMarkets.markets": + list := []string{} + return protoreflect.ValueOfList(&_MsgRemoveMarkets_2_list{list: &list}) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: connect.marketmap.v2.MsgRemoveMarkets")) + } + panic(fmt.Errorf("message connect.marketmap.v2.MsgRemoveMarkets does not contain field %s", fd.FullName())) + } +} + +// WhichOneof reports which field within the oneof is populated, +// returning nil if none are populated. +// It panics if the oneof descriptor does not belong to this message. +func (x *fastReflection_MsgRemoveMarkets) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in connect.marketmap.v2.MsgRemoveMarkets", d.FullName())) + } + panic("unreachable") +} + +// GetUnknown retrieves the entire list of unknown fields. +// The caller may only mutate the contents of the RawFields +// if the mutated bytes are stored back into the message with SetUnknown. +func (x *fastReflection_MsgRemoveMarkets) GetUnknown() protoreflect.RawFields { + return x.unknownFields +} + +// SetUnknown stores an entire list of unknown fields. +// The raw fields must be syntactically valid according to the wire format. +// An implementation may panic if this is not the case. +// Once stored, the caller must not mutate the content of the RawFields. +// An empty RawFields may be passed to clear the fields. +// +// SetUnknown is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_MsgRemoveMarkets) SetUnknown(fields protoreflect.RawFields) { + x.unknownFields = fields +} + +// IsValid reports whether the message is valid. +// +// An invalid message is an empty, read-only value. +// +// An invalid message often corresponds to a nil pointer of the concrete +// message type, but the details are implementation dependent. +// Validity is not part of the protobuf data model, and may not +// be preserved in marshaling or other operations. +func (x *fastReflection_MsgRemoveMarkets) IsValid() bool { + return x != nil +} + +// ProtoMethods returns optional fastReflectionFeature-path implementations of various operations. +// This method may return nil. +// +// The returned methods type is identical to +// "google.golang.org/protobuf/runtime/protoiface".Methods. +// Consult the protoiface package documentation for details. +func (x *fastReflection_MsgRemoveMarkets) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*MsgRemoveMarkets) + if x == nil { + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: 0, + } + } + options := runtime.SizeInputToOptions(input) + _ = options + var n int + var l int + _ = l + l = len(x.Admin) + if l > 0 { + n += 1 + l + runtime.Sov(uint64(l)) + } + if len(x.Markets) > 0 { + for _, s := range x.Markets { + l = len(s) + n += 1 + l + runtime.Sov(uint64(l)) + } + } + if x.unknownFields != nil { + n += len(x.unknownFields) + } + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: n, + } + } + + marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) { + x := input.Message.Interface().(*MsgRemoveMarkets) + if x == nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + options := runtime.MarshalInputToOptions(input) + _ = options + size := options.Size(x) + dAtA := make([]byte, size) + i := len(dAtA) + _ = i + var l int + _ = l + if x.unknownFields != nil { + i -= len(x.unknownFields) + copy(dAtA[i:], x.unknownFields) + } + if len(x.Markets) > 0 { + for iNdEx := len(x.Markets) - 1; iNdEx >= 0; iNdEx-- { + i -= len(x.Markets[iNdEx]) + copy(dAtA[i:], x.Markets[iNdEx]) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.Markets[iNdEx]))) + i-- + dAtA[i] = 0x12 + } + } + if len(x.Admin) > 0 { + i -= len(x.Admin) + copy(dAtA[i:], x.Admin) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.Admin))) + i-- + dAtA[i] = 0xa + } + if input.Buf != nil { + input.Buf = append(input.Buf, dAtA...) + } else { + input.Buf = dAtA + } + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + unmarshal := func(input protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { + x := input.Message.Interface().(*MsgRemoveMarkets) + if x == nil { + return protoiface.UnmarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Flags: input.Flags, + }, nil + } + options := runtime.UnmarshalInputToOptions(input) + _ = options + dAtA := input.Buf + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, 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 protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: MsgRemoveMarkets: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: MsgRemoveMarkets: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Admin", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.Admin = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field Markets", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.Markets = append(x.Markets, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := runtime.Skip(dAtA[iNdEx:]) + if err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if !options.DiscardUnknown { + x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + } + iNdEx += skippy + } + } + + if iNdEx > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil + } + return &protoiface.Methods{ + NoUnkeyedLiterals: struct{}{}, + Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown, + Size: size, + Marshal: marshal, + Unmarshal: unmarshal, + Merge: nil, + CheckInitialized: nil, + } +} + +var _ protoreflect.List = (*_MsgRemoveMarketsResponse_1_list)(nil) + +type _MsgRemoveMarketsResponse_1_list struct { + list *[]string +} + +func (x *_MsgRemoveMarketsResponse_1_list) Len() int { + if x.list == nil { + return 0 + } + return len(*x.list) +} + +func (x *_MsgRemoveMarketsResponse_1_list) Get(i int) protoreflect.Value { + return protoreflect.ValueOfString((*x.list)[i]) +} + +func (x *_MsgRemoveMarketsResponse_1_list) Set(i int, value protoreflect.Value) { + valueUnwrapped := value.String() + concreteValue := valueUnwrapped + (*x.list)[i] = concreteValue +} + +func (x *_MsgRemoveMarketsResponse_1_list) Append(value protoreflect.Value) { + valueUnwrapped := value.String() + concreteValue := valueUnwrapped + *x.list = append(*x.list, concreteValue) +} + +func (x *_MsgRemoveMarketsResponse_1_list) AppendMutable() protoreflect.Value { + panic(fmt.Errorf("AppendMutable can not be called on message MsgRemoveMarketsResponse at list field DeletedMarkets as it is not of Message kind")) +} + +func (x *_MsgRemoveMarketsResponse_1_list) Truncate(n int) { + *x.list = (*x.list)[:n] +} + +func (x *_MsgRemoveMarketsResponse_1_list) NewElement() protoreflect.Value { + v := "" + return protoreflect.ValueOfString(v) +} + +func (x *_MsgRemoveMarketsResponse_1_list) IsValid() bool { + return x.list != nil +} + +var ( + md_MsgRemoveMarketsResponse protoreflect.MessageDescriptor + fd_MsgRemoveMarketsResponse_deleted_markets protoreflect.FieldDescriptor +) + +func init() { + file_connect_marketmap_v2_tx_proto_init() + md_MsgRemoveMarketsResponse = File_connect_marketmap_v2_tx_proto.Messages().ByName("MsgRemoveMarketsResponse") + fd_MsgRemoveMarketsResponse_deleted_markets = md_MsgRemoveMarketsResponse.Fields().ByName("deleted_markets") +} + +var _ protoreflect.Message = (*fastReflection_MsgRemoveMarketsResponse)(nil) + +type fastReflection_MsgRemoveMarketsResponse MsgRemoveMarketsResponse + +func (x *MsgRemoveMarketsResponse) ProtoReflect() protoreflect.Message { + return (*fastReflection_MsgRemoveMarketsResponse)(x) +} + +func (x *MsgRemoveMarketsResponse) slowProtoReflect() protoreflect.Message { + mi := &file_connect_marketmap_v2_tx_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +var _fastReflection_MsgRemoveMarketsResponse_messageType fastReflection_MsgRemoveMarketsResponse_messageType +var _ protoreflect.MessageType = fastReflection_MsgRemoveMarketsResponse_messageType{} + +type fastReflection_MsgRemoveMarketsResponse_messageType struct{} + +func (x fastReflection_MsgRemoveMarketsResponse_messageType) Zero() protoreflect.Message { + return (*fastReflection_MsgRemoveMarketsResponse)(nil) +} +func (x fastReflection_MsgRemoveMarketsResponse_messageType) New() protoreflect.Message { + return new(fastReflection_MsgRemoveMarketsResponse) +} +func (x fastReflection_MsgRemoveMarketsResponse_messageType) Descriptor() protoreflect.MessageDescriptor { + return md_MsgRemoveMarketsResponse +} + +// Descriptor returns message descriptor, which contains only the protobuf +// type information for the message. +func (x *fastReflection_MsgRemoveMarketsResponse) Descriptor() protoreflect.MessageDescriptor { + return md_MsgRemoveMarketsResponse +} + +// Type returns the message type, which encapsulates both Go and protobuf +// type information. If the Go type information is not needed, +// it is recommended that the message descriptor be used instead. +func (x *fastReflection_MsgRemoveMarketsResponse) Type() protoreflect.MessageType { + return _fastReflection_MsgRemoveMarketsResponse_messageType +} + +// New returns a newly allocated and mutable empty message. +func (x *fastReflection_MsgRemoveMarketsResponse) New() protoreflect.Message { + return new(fastReflection_MsgRemoveMarketsResponse) +} + +// Interface unwraps the message reflection interface and +// returns the underlying ProtoMessage interface. +func (x *fastReflection_MsgRemoveMarketsResponse) Interface() protoreflect.ProtoMessage { + return (*MsgRemoveMarketsResponse)(x) +} + +// Range iterates over every populated field in an undefined order, +// calling f for each field descriptor and value encountered. +// Range returns immediately if f returns false. +// While iterating, mutating operations may only be performed +// on the current field descriptor. +func (x *fastReflection_MsgRemoveMarketsResponse) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { + if len(x.DeletedMarkets) != 0 { + value := protoreflect.ValueOfList(&_MsgRemoveMarketsResponse_1_list{list: &x.DeletedMarkets}) + if !f(fd_MsgRemoveMarketsResponse_deleted_markets, value) { + return + } + } +} + +// Has reports whether a field is populated. +// +// Some fields have the property of nullability where it is possible to +// distinguish between the default value of a field and whether the field +// was explicitly populated with the default value. Singular message fields, +// member fields of a oneof, and proto2 scalar fields are nullable. Such +// fields are populated only if explicitly set. +// +// In other cases (aside from the nullable cases above), +// a proto3 scalar field is populated if it contains a non-zero value, and +// a repeated field is populated if it is non-empty. +func (x *fastReflection_MsgRemoveMarketsResponse) Has(fd protoreflect.FieldDescriptor) bool { + switch fd.FullName() { + case "connect.marketmap.v2.MsgRemoveMarketsResponse.deleted_markets": + return len(x.DeletedMarkets) != 0 + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: connect.marketmap.v2.MsgRemoveMarketsResponse")) + } + panic(fmt.Errorf("message connect.marketmap.v2.MsgRemoveMarketsResponse does not contain field %s", fd.FullName())) + } +} + +// Clear clears the field such that a subsequent Has call reports false. +// +// Clearing an extension field clears both the extension type and value +// associated with the given field number. +// +// Clear is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_MsgRemoveMarketsResponse) Clear(fd protoreflect.FieldDescriptor) { + switch fd.FullName() { + case "connect.marketmap.v2.MsgRemoveMarketsResponse.deleted_markets": + x.DeletedMarkets = nil + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: connect.marketmap.v2.MsgRemoveMarketsResponse")) + } + panic(fmt.Errorf("message connect.marketmap.v2.MsgRemoveMarketsResponse does not contain field %s", fd.FullName())) + } +} + +// Get retrieves the value for a field. +// +// For unpopulated scalars, it returns the default value, where +// the default value of a bytes scalar is guaranteed to be a copy. +// For unpopulated composite types, it returns an empty, read-only view +// of the value; to obtain a mutable reference, use Mutable. +func (x *fastReflection_MsgRemoveMarketsResponse) Get(descriptor protoreflect.FieldDescriptor) protoreflect.Value { + switch descriptor.FullName() { + case "connect.marketmap.v2.MsgRemoveMarketsResponse.deleted_markets": + if len(x.DeletedMarkets) == 0 { + return protoreflect.ValueOfList(&_MsgRemoveMarketsResponse_1_list{}) + } + listValue := &_MsgRemoveMarketsResponse_1_list{list: &x.DeletedMarkets} + return protoreflect.ValueOfList(listValue) + default: + if descriptor.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: connect.marketmap.v2.MsgRemoveMarketsResponse")) + } + panic(fmt.Errorf("message connect.marketmap.v2.MsgRemoveMarketsResponse does not contain field %s", descriptor.FullName())) + } +} + +// Set stores the value for a field. +// +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType. +// When setting a composite type, it is unspecified whether the stored value +// aliases the source's memory in any way. If the composite value is an +// empty, read-only value, then it panics. +// +// Set is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_MsgRemoveMarketsResponse) Set(fd protoreflect.FieldDescriptor, value protoreflect.Value) { + switch fd.FullName() { + case "connect.marketmap.v2.MsgRemoveMarketsResponse.deleted_markets": + lv := value.List() + clv := lv.(*_MsgRemoveMarketsResponse_1_list) + x.DeletedMarkets = *clv.list + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: connect.marketmap.v2.MsgRemoveMarketsResponse")) + } + panic(fmt.Errorf("message connect.marketmap.v2.MsgRemoveMarketsResponse does not contain field %s", fd.FullName())) + } +} + +// Mutable returns a mutable reference to a composite type. +// +// If the field is unpopulated, it may allocate a composite value. +// For a field belonging to a oneof, it implicitly clears any other field +// that may be currently set within the same oneof. +// For extension fields, it implicitly stores the provided ExtensionType +// if not already stored. +// It panics if the field does not contain a composite type. +// +// Mutable is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_MsgRemoveMarketsResponse) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "connect.marketmap.v2.MsgRemoveMarketsResponse.deleted_markets": + if x.DeletedMarkets == nil { + x.DeletedMarkets = []string{} + } + value := &_MsgRemoveMarketsResponse_1_list{list: &x.DeletedMarkets} + return protoreflect.ValueOfList(value) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: connect.marketmap.v2.MsgRemoveMarketsResponse")) + } + panic(fmt.Errorf("message connect.marketmap.v2.MsgRemoveMarketsResponse does not contain field %s", fd.FullName())) + } +} + +// NewField returns a new value that is assignable to the field +// for the given descriptor. For scalars, this returns the default value. +// For lists, maps, and messages, this returns a new, empty, mutable value. +func (x *fastReflection_MsgRemoveMarketsResponse) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { + switch fd.FullName() { + case "connect.marketmap.v2.MsgRemoveMarketsResponse.deleted_markets": + list := []string{} + return protoreflect.ValueOfList(&_MsgRemoveMarketsResponse_1_list{list: &list}) + default: + if fd.IsExtension() { + panic(fmt.Errorf("proto3 declared messages do not support extensions: connect.marketmap.v2.MsgRemoveMarketsResponse")) + } + panic(fmt.Errorf("message connect.marketmap.v2.MsgRemoveMarketsResponse does not contain field %s", fd.FullName())) + } +} + +// WhichOneof reports which field within the oneof is populated, +// returning nil if none are populated. +// It panics if the oneof descriptor does not belong to this message. +func (x *fastReflection_MsgRemoveMarketsResponse) WhichOneof(d protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { + switch d.FullName() { + default: + panic(fmt.Errorf("%s is not a oneof field in connect.marketmap.v2.MsgRemoveMarketsResponse", d.FullName())) + } + panic("unreachable") +} + +// GetUnknown retrieves the entire list of unknown fields. +// The caller may only mutate the contents of the RawFields +// if the mutated bytes are stored back into the message with SetUnknown. +func (x *fastReflection_MsgRemoveMarketsResponse) GetUnknown() protoreflect.RawFields { + return x.unknownFields +} + +// SetUnknown stores an entire list of unknown fields. +// The raw fields must be syntactically valid according to the wire format. +// An implementation may panic if this is not the case. +// Once stored, the caller must not mutate the content of the RawFields. +// An empty RawFields may be passed to clear the fields. +// +// SetUnknown is a mutating operation and unsafe for concurrent use. +func (x *fastReflection_MsgRemoveMarketsResponse) SetUnknown(fields protoreflect.RawFields) { + x.unknownFields = fields +} + +// IsValid reports whether the message is valid. +// +// An invalid message is an empty, read-only value. +// +// An invalid message often corresponds to a nil pointer of the concrete +// message type, but the details are implementation dependent. +// Validity is not part of the protobuf data model, and may not +// be preserved in marshaling or other operations. +func (x *fastReflection_MsgRemoveMarketsResponse) IsValid() bool { + return x != nil +} + +// ProtoMethods returns optional fastReflectionFeature-path implementations of various operations. +// This method may return nil. +// +// The returned methods type is identical to +// "google.golang.org/protobuf/runtime/protoiface".Methods. +// Consult the protoiface package documentation for details. +func (x *fastReflection_MsgRemoveMarketsResponse) ProtoMethods() *protoiface.Methods { + size := func(input protoiface.SizeInput) protoiface.SizeOutput { + x := input.Message.Interface().(*MsgRemoveMarketsResponse) + if x == nil { + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: 0, + } + } + options := runtime.SizeInputToOptions(input) + _ = options + var n int + var l int + _ = l + if len(x.DeletedMarkets) > 0 { + for _, s := range x.DeletedMarkets { + l = len(s) + n += 1 + l + runtime.Sov(uint64(l)) + } + } + if x.unknownFields != nil { + n += len(x.unknownFields) + } + return protoiface.SizeOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Size: n, + } + } + + marshal := func(input protoiface.MarshalInput) (protoiface.MarshalOutput, error) { + x := input.Message.Interface().(*MsgRemoveMarketsResponse) + if x == nil { + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + options := runtime.MarshalInputToOptions(input) + _ = options + size := options.Size(x) + dAtA := make([]byte, size) + i := len(dAtA) + _ = i + var l int + _ = l + if x.unknownFields != nil { + i -= len(x.unknownFields) + copy(dAtA[i:], x.unknownFields) + } + if len(x.DeletedMarkets) > 0 { + for iNdEx := len(x.DeletedMarkets) - 1; iNdEx >= 0; iNdEx-- { + i -= len(x.DeletedMarkets[iNdEx]) + copy(dAtA[i:], x.DeletedMarkets[iNdEx]) + i = runtime.EncodeVarint(dAtA, i, uint64(len(x.DeletedMarkets[iNdEx]))) + i-- + dAtA[i] = 0xa + } + } + if input.Buf != nil { + input.Buf = append(input.Buf, dAtA...) + } else { + input.Buf = dAtA + } + return protoiface.MarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Buf: input.Buf, + }, nil + } + unmarshal := func(input protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { + x := input.Message.Interface().(*MsgRemoveMarketsResponse) + if x == nil { + return protoiface.UnmarshalOutput{ + NoUnkeyedLiterals: input.NoUnkeyedLiterals, + Flags: input.Flags, + }, nil + } + options := runtime.UnmarshalInputToOptions(input) + _ = options + dAtA := input.Buf + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, 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 protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: MsgRemoveMarketsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: MsgRemoveMarketsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, fmt.Errorf("proto: wrong wireType = %d for field DeletedMarkets", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrIntOverflow + } + if iNdEx >= l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if postIndex > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + x.DeletedMarkets = append(x.DeletedMarkets, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := runtime.Skip(dAtA[iNdEx:]) + if err != nil { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, runtime.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + if !options.DiscardUnknown { + x.unknownFields = append(x.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + } + iNdEx += skippy + } + } + + if iNdEx > l { + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, io.ErrUnexpectedEOF + } + return protoiface.UnmarshalOutput{NoUnkeyedLiterals: input.NoUnkeyedLiterals, Flags: input.Flags}, nil + } + return &protoiface.Methods{ + NoUnkeyedLiterals: struct{}{}, + Flags: protoiface.SupportMarshalDeterministic | protoiface.SupportUnmarshalDiscardUnknown, + Size: size, + Marshal: marshal, + Unmarshal: unmarshal, + Merge: nil, + CheckInitialized: nil, + } +} + // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.0 @@ -5218,6 +6242,92 @@ func (*MsgRemoveMarketAuthoritiesResponse) Descriptor() ([]byte, []int) { return file_connect_marketmap_v2_tx_proto_rawDescGZIP(), []int{9} } +// MsgRemoveMarkets defines the Msg/RemoveMarkets request type. It contains the +// new markets to be removed from the market map. +type MsgRemoveMarkets struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Admin defines the authority that is the x/marketmap + // Admin account. This account is set in the module parameters. + Admin string `protobuf:"bytes,1,opt,name=admin,proto3" json:"admin,omitempty"` + // Markets is the list of markets to remove. + Markets []string `protobuf:"bytes,2,rep,name=markets,proto3" json:"markets,omitempty"` +} + +func (x *MsgRemoveMarkets) Reset() { + *x = MsgRemoveMarkets{} + if protoimpl.UnsafeEnabled { + mi := &file_connect_marketmap_v2_tx_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MsgRemoveMarkets) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MsgRemoveMarkets) ProtoMessage() {} + +// Deprecated: Use MsgRemoveMarkets.ProtoReflect.Descriptor instead. +func (*MsgRemoveMarkets) Descriptor() ([]byte, []int) { + return file_connect_marketmap_v2_tx_proto_rawDescGZIP(), []int{10} +} + +func (x *MsgRemoveMarkets) GetAdmin() string { + if x != nil { + return x.Admin + } + return "" +} + +func (x *MsgRemoveMarkets) GetMarkets() []string { + if x != nil { + return x.Markets + } + return nil +} + +// MsgRemoveMarketsResponse defines the +// Msg/MsgRemoveMarketsResponse response type. +type MsgRemoveMarketsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // DeletedMarkets is the list of markets that were removed. + DeletedMarkets []string `protobuf:"bytes,1,rep,name=deleted_markets,json=deletedMarkets,proto3" json:"deleted_markets,omitempty"` +} + +func (x *MsgRemoveMarketsResponse) Reset() { + *x = MsgRemoveMarketsResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_connect_marketmap_v2_tx_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MsgRemoveMarketsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MsgRemoveMarketsResponse) ProtoMessage() {} + +// Deprecated: Use MsgRemoveMarketsResponse.ProtoReflect.Descriptor instead. +func (*MsgRemoveMarketsResponse) Descriptor() ([]byte, []int) { + return file_connect_marketmap_v2_tx_proto_rawDescGZIP(), []int{11} +} + +func (x *MsgRemoveMarketsResponse) GetDeletedMarkets() []string { + if x != nil { + return x.DeletedMarkets + } + return nil +} + var File_connect_marketmap_v2_tx_proto protoreflect.FileDescriptor var file_connect_marketmap_v2_tx_proto_rawDesc = []byte{ @@ -5311,55 +6421,72 @@ var file_connect_marketmap_v2_tx_proto_rawDesc = []byte{ 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x3a, 0x0a, 0x82, 0xe7, 0xb0, 0x2a, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x22, 0x24, 0x0a, 0x22, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x65, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xa9, 0x04, 0x0a, 0x03, 0x4d, 0x73, 0x67, - 0x12, 0x67, 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, - 0x73, 0x12, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x6d, 0x61, 0x72, 0x6b, - 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x73, 0x67, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x73, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x68, 0x0a, 0x10, 0x4d, 0x73, 0x67, 0x52, + 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x73, 0x12, 0x2e, 0x0a, 0x05, + 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x18, 0xd2, 0xb4, 0x2d, + 0x14, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x53, + 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x12, 0x18, 0x0a, 0x07, + 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x6d, + 0x61, 0x72, 0x6b, 0x65, 0x74, 0x73, 0x3a, 0x0a, 0x82, 0xe7, 0xb0, 0x2a, 0x05, 0x61, 0x64, 0x6d, + 0x69, 0x6e, 0x22, 0x43, 0x0a, 0x18, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4d, + 0x61, 0x72, 0x6b, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, + 0x0a, 0x0f, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x74, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, + 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x73, 0x32, 0x92, 0x05, 0x0a, 0x03, 0x4d, 0x73, 0x67, 0x12, + 0x67, 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x73, + 0x12, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x6d, 0x61, 0x72, 0x6b, 0x65, + 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x73, 0x67, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x73, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x2e, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x76, 0x32, 0x2e, + 0x4d, 0x73, 0x67, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x67, 0x0a, 0x0d, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x73, 0x12, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x76, 0x32, - 0x2e, 0x4d, 0x73, 0x67, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x67, 0x0a, 0x0d, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x73, 0x12, 0x26, 0x2e, 0x63, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x76, - 0x32, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x72, 0x6b, 0x65, - 0x74, 0x73, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x6d, 0x61, 0x72, - 0x6b, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x58, 0x0a, 0x0c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, - 0x6d, 0x73, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x6d, 0x61, 0x72, + 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, + 0x73, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x6d, 0x61, 0x72, 0x6b, + 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x58, 0x0a, 0x0c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, + 0x73, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x6d, 0x61, 0x72, 0x6b, + 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x73, 0x67, 0x50, 0x61, 0x72, 0x61, + 0x6d, 0x73, 0x1a, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x73, 0x67, 0x50, 0x61, 0x72, - 0x61, 0x6d, 0x73, 0x1a, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x6d, 0x61, - 0x72, 0x6b, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x73, 0x67, 0x50, 0x61, - 0x72, 0x61, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x85, 0x01, 0x0a, - 0x17, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x41, 0x75, 0x74, - 0x68, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x2e, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x76, 0x32, 0x2e, - 0x4d, 0x73, 0x67, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x41, - 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x65, 0x73, 0x1a, 0x38, 0x2e, 0x63, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x76, - 0x32, 0x2e, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4d, 0x61, 0x72, 0x6b, 0x65, - 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x67, 0x0a, 0x0d, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x4d, 0x61, - 0x72, 0x6b, 0x65, 0x74, 0x73, 0x12, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, - 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x73, 0x67, - 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x73, 0x1a, 0x2e, 0x2e, + 0x61, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x85, 0x01, 0x0a, 0x17, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x41, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0x2e, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x76, 0x32, 0x2e, 0x4d, + 0x73, 0x67, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x41, 0x75, + 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x65, 0x73, 0x1a, 0x38, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, + 0x65, 0x63, 0x74, 0x2e, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x76, 0x32, + 0x2e, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, + 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x67, 0x0a, 0x0d, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x4d, 0x61, 0x72, + 0x6b, 0x65, 0x74, 0x73, 0x12, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x6d, + 0x61, 0x72, 0x6b, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x73, 0x67, 0x55, + 0x70, 0x73, 0x65, 0x72, 0x74, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x73, 0x1a, 0x2e, 0x2e, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x6d, 0x61, 0x70, + 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x4d, 0x61, 0x72, + 0x6b, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x67, 0x0a, 0x0d, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x73, 0x12, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x6d, 0x61, - 0x70, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x73, 0x67, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x4d, 0x61, - 0x72, 0x6b, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x05, 0x80, - 0xe7, 0xb0, 0x2a, 0x01, 0x42, 0xc8, 0x01, 0x0a, 0x18, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x76, - 0x32, 0x42, 0x07, 0x54, 0x78, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x31, 0x63, 0x6f, - 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2f, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x6d, 0x61, 0x70, - 0x2f, 0x76, 0x32, 0x3b, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x76, 0x32, 0xa2, - 0x02, 0x03, 0x43, 0x4d, 0x58, 0xaa, 0x02, 0x14, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, - 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x56, 0x32, 0xca, 0x02, 0x14, 0x43, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5c, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x6d, 0x61, 0x70, - 0x5c, 0x56, 0x32, 0xe2, 0x02, 0x20, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5c, 0x4d, 0x61, - 0x72, 0x6b, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x5c, 0x56, 0x32, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x16, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, - 0x3a, 0x3a, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x3a, 0x3a, 0x56, 0x32, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x70, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x73, 0x67, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4d, 0x61, + 0x72, 0x6b, 0x65, 0x74, 0x73, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, + 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x73, 0x67, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x05, 0x80, 0xe7, 0xb0, 0x2a, 0x01, 0x42, 0xc8, 0x01, 0x0a, + 0x18, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x6d, 0x61, 0x72, + 0x6b, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2e, 0x76, 0x32, 0x42, 0x07, 0x54, 0x78, 0x50, 0x72, 0x6f, + 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x31, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x73, 0x73, 0x64, 0x6b, 0x2e, + 0x69, 0x6f, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2f, 0x6d, + 0x61, 0x72, 0x6b, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x2f, 0x76, 0x32, 0x3b, 0x6d, 0x61, 0x72, 0x6b, + 0x65, 0x74, 0x6d, 0x61, 0x70, 0x76, 0x32, 0xa2, 0x02, 0x03, 0x43, 0x4d, 0x58, 0xaa, 0x02, 0x14, + 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x6d, 0x61, + 0x70, 0x2e, 0x56, 0x32, 0xca, 0x02, 0x14, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5c, 0x4d, + 0x61, 0x72, 0x6b, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x5c, 0x56, 0x32, 0xe2, 0x02, 0x20, 0x43, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5c, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x5c, + 0x56, 0x32, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, + 0x16, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x3a, 0x3a, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, + 0x6d, 0x61, 0x70, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -5374,7 +6501,7 @@ func file_connect_marketmap_v2_tx_proto_rawDescGZIP() []byte { return file_connect_marketmap_v2_tx_proto_rawDescData } -var file_connect_marketmap_v2_tx_proto_msgTypes = make([]protoimpl.MessageInfo, 11) +var file_connect_marketmap_v2_tx_proto_msgTypes = make([]protoimpl.MessageInfo, 13) var file_connect_marketmap_v2_tx_proto_goTypes = []interface{}{ (*MsgUpsertMarkets)(nil), // 0: connect.marketmap.v2.MsgUpsertMarkets (*MsgUpsertMarketsResponse)(nil), // 1: connect.marketmap.v2.MsgUpsertMarketsResponse @@ -5386,28 +6513,32 @@ var file_connect_marketmap_v2_tx_proto_goTypes = []interface{}{ (*MsgParamsResponse)(nil), // 7: connect.marketmap.v2.MsgParamsResponse (*MsgRemoveMarketAuthorities)(nil), // 8: connect.marketmap.v2.MsgRemoveMarketAuthorities (*MsgRemoveMarketAuthoritiesResponse)(nil), // 9: connect.marketmap.v2.MsgRemoveMarketAuthoritiesResponse - nil, // 10: connect.marketmap.v2.MsgUpsertMarketsResponse.MarketUpdatesEntry - (*Market)(nil), // 11: connect.marketmap.v2.Market - (*Params)(nil), // 12: connect.marketmap.v2.Params + (*MsgRemoveMarkets)(nil), // 10: connect.marketmap.v2.MsgRemoveMarkets + (*MsgRemoveMarketsResponse)(nil), // 11: connect.marketmap.v2.MsgRemoveMarketsResponse + nil, // 12: connect.marketmap.v2.MsgUpsertMarketsResponse.MarketUpdatesEntry + (*Market)(nil), // 13: connect.marketmap.v2.Market + (*Params)(nil), // 14: connect.marketmap.v2.Params } var file_connect_marketmap_v2_tx_proto_depIdxs = []int32{ - 11, // 0: connect.marketmap.v2.MsgUpsertMarkets.markets:type_name -> connect.marketmap.v2.Market - 10, // 1: connect.marketmap.v2.MsgUpsertMarketsResponse.market_updates:type_name -> connect.marketmap.v2.MsgUpsertMarketsResponse.MarketUpdatesEntry - 11, // 2: connect.marketmap.v2.MsgCreateMarkets.create_markets:type_name -> connect.marketmap.v2.Market - 11, // 3: connect.marketmap.v2.MsgUpdateMarkets.update_markets:type_name -> connect.marketmap.v2.Market - 12, // 4: connect.marketmap.v2.MsgParams.params:type_name -> connect.marketmap.v2.Params + 13, // 0: connect.marketmap.v2.MsgUpsertMarkets.markets:type_name -> connect.marketmap.v2.Market + 12, // 1: connect.marketmap.v2.MsgUpsertMarketsResponse.market_updates:type_name -> connect.marketmap.v2.MsgUpsertMarketsResponse.MarketUpdatesEntry + 13, // 2: connect.marketmap.v2.MsgCreateMarkets.create_markets:type_name -> connect.marketmap.v2.Market + 13, // 3: connect.marketmap.v2.MsgUpdateMarkets.update_markets:type_name -> connect.marketmap.v2.Market + 14, // 4: connect.marketmap.v2.MsgParams.params:type_name -> connect.marketmap.v2.Params 2, // 5: connect.marketmap.v2.Msg.CreateMarkets:input_type -> connect.marketmap.v2.MsgCreateMarkets 4, // 6: connect.marketmap.v2.Msg.UpdateMarkets:input_type -> connect.marketmap.v2.MsgUpdateMarkets 6, // 7: connect.marketmap.v2.Msg.UpdateParams:input_type -> connect.marketmap.v2.MsgParams 8, // 8: connect.marketmap.v2.Msg.RemoveMarketAuthorities:input_type -> connect.marketmap.v2.MsgRemoveMarketAuthorities 0, // 9: connect.marketmap.v2.Msg.UpsertMarkets:input_type -> connect.marketmap.v2.MsgUpsertMarkets - 3, // 10: connect.marketmap.v2.Msg.CreateMarkets:output_type -> connect.marketmap.v2.MsgCreateMarketsResponse - 5, // 11: connect.marketmap.v2.Msg.UpdateMarkets:output_type -> connect.marketmap.v2.MsgUpdateMarketsResponse - 7, // 12: connect.marketmap.v2.Msg.UpdateParams:output_type -> connect.marketmap.v2.MsgParamsResponse - 9, // 13: connect.marketmap.v2.Msg.RemoveMarketAuthorities:output_type -> connect.marketmap.v2.MsgRemoveMarketAuthoritiesResponse - 1, // 14: connect.marketmap.v2.Msg.UpsertMarkets:output_type -> connect.marketmap.v2.MsgUpsertMarketsResponse - 10, // [10:15] is the sub-list for method output_type - 5, // [5:10] is the sub-list for method input_type + 10, // 10: connect.marketmap.v2.Msg.RemoveMarkets:input_type -> connect.marketmap.v2.MsgRemoveMarkets + 3, // 11: connect.marketmap.v2.Msg.CreateMarkets:output_type -> connect.marketmap.v2.MsgCreateMarketsResponse + 5, // 12: connect.marketmap.v2.Msg.UpdateMarkets:output_type -> connect.marketmap.v2.MsgUpdateMarketsResponse + 7, // 13: connect.marketmap.v2.Msg.UpdateParams:output_type -> connect.marketmap.v2.MsgParamsResponse + 9, // 14: connect.marketmap.v2.Msg.RemoveMarketAuthorities:output_type -> connect.marketmap.v2.MsgRemoveMarketAuthoritiesResponse + 1, // 15: connect.marketmap.v2.Msg.UpsertMarkets:output_type -> connect.marketmap.v2.MsgUpsertMarketsResponse + 11, // 16: connect.marketmap.v2.Msg.RemoveMarkets:output_type -> connect.marketmap.v2.MsgRemoveMarketsResponse + 11, // [11:17] is the sub-list for method output_type + 5, // [5:11] is the sub-list for method input_type 5, // [5:5] is the sub-list for extension type_name 5, // [5:5] is the sub-list for extension extendee 0, // [0:5] is the sub-list for field type_name @@ -5541,6 +6672,30 @@ func file_connect_marketmap_v2_tx_proto_init() { return nil } } + file_connect_marketmap_v2_tx_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MsgRemoveMarkets); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_connect_marketmap_v2_tx_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MsgRemoveMarketsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -5548,7 +6703,7 @@ func file_connect_marketmap_v2_tx_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_connect_marketmap_v2_tx_proto_rawDesc, NumEnums: 0, - NumMessages: 11, + NumMessages: 13, NumExtensions: 0, NumServices: 1, }, diff --git a/api/connect/marketmap/v2/tx_grpc.pb.go b/api/connect/marketmap/v2/tx_grpc.pb.go index 232d972e3..e63b8d023 100644 --- a/api/connect/marketmap/v2/tx_grpc.pb.go +++ b/api/connect/marketmap/v2/tx_grpc.pb.go @@ -24,6 +24,7 @@ const ( Msg_UpdateParams_FullMethodName = "/connect.marketmap.v2.Msg/UpdateParams" Msg_RemoveMarketAuthorities_FullMethodName = "/connect.marketmap.v2.Msg/RemoveMarketAuthorities" Msg_UpsertMarkets_FullMethodName = "/connect.marketmap.v2.Msg/UpsertMarkets" + Msg_RemoveMarkets_FullMethodName = "/connect.marketmap.v2.Msg/RemoveMarkets" ) // MsgClient is the client API for Msg service. @@ -46,6 +47,10 @@ type MsgClient interface { // Specifically if a market does not exist it will be created, otherwise it // will be updated. The response will be a map between ticker -> updated. UpsertMarkets(ctx context.Context, in *MsgUpsertMarkets, opts ...grpc.CallOption) (*MsgUpsertMarketsResponse, error) + // RemoveMarkets removes the given markets from the marketmap if: + // - they exist in the map + // - they are disabled + RemoveMarkets(ctx context.Context, in *MsgRemoveMarkets, opts ...grpc.CallOption) (*MsgRemoveMarketsResponse, error) } type msgClient struct { @@ -106,6 +111,16 @@ func (c *msgClient) UpsertMarkets(ctx context.Context, in *MsgUpsertMarkets, opt return out, nil } +func (c *msgClient) RemoveMarkets(ctx context.Context, in *MsgRemoveMarkets, opts ...grpc.CallOption) (*MsgRemoveMarketsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(MsgRemoveMarketsResponse) + err := c.cc.Invoke(ctx, Msg_RemoveMarkets_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + // MsgServer is the server API for Msg service. // All implementations must embed UnimplementedMsgServer // for forward compatibility. @@ -126,6 +141,10 @@ type MsgServer interface { // Specifically if a market does not exist it will be created, otherwise it // will be updated. The response will be a map between ticker -> updated. UpsertMarkets(context.Context, *MsgUpsertMarkets) (*MsgUpsertMarketsResponse, error) + // RemoveMarkets removes the given markets from the marketmap if: + // - they exist in the map + // - they are disabled + RemoveMarkets(context.Context, *MsgRemoveMarkets) (*MsgRemoveMarketsResponse, error) mustEmbedUnimplementedMsgServer() } @@ -151,6 +170,9 @@ func (UnimplementedMsgServer) RemoveMarketAuthorities(context.Context, *MsgRemov func (UnimplementedMsgServer) UpsertMarkets(context.Context, *MsgUpsertMarkets) (*MsgUpsertMarketsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method UpsertMarkets not implemented") } +func (UnimplementedMsgServer) RemoveMarkets(context.Context, *MsgRemoveMarkets) (*MsgRemoveMarketsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RemoveMarkets not implemented") +} func (UnimplementedMsgServer) mustEmbedUnimplementedMsgServer() {} func (UnimplementedMsgServer) testEmbeddedByValue() {} @@ -262,6 +284,24 @@ func _Msg_UpsertMarkets_Handler(srv interface{}, ctx context.Context, dec func(i return interceptor(ctx, in, info, handler) } +func _Msg_RemoveMarkets_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgRemoveMarkets) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).RemoveMarkets(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Msg_RemoveMarkets_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).RemoveMarkets(ctx, req.(*MsgRemoveMarkets)) + } + return interceptor(ctx, in, info, handler) +} + // Msg_ServiceDesc is the grpc.ServiceDesc for Msg service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -289,6 +329,10 @@ var Msg_ServiceDesc = grpc.ServiceDesc{ MethodName: "UpsertMarkets", Handler: _Msg_UpsertMarkets_Handler, }, + { + MethodName: "RemoveMarkets", + Handler: _Msg_RemoveMarkets_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "connect/marketmap/v2/tx.proto", diff --git a/proto/connect/marketmap/v2/tx.proto b/proto/connect/marketmap/v2/tx.proto index 6c479f3b4..491aaaef2 100644 --- a/proto/connect/marketmap/v2/tx.proto +++ b/proto/connect/marketmap/v2/tx.proto @@ -33,6 +33,11 @@ service Msg { // Specifically if a market does not exist it will be created, otherwise it // will be updated. The response will be a map between ticker -> updated. rpc UpsertMarkets(MsgUpsertMarkets) returns (MsgUpsertMarketsResponse); + + // RemoveMarkets removes the given markets from the marketmap if: + // - they exist in the map + // - they are disabled + rpc RemoveMarkets(MsgRemoveMarkets) returns (MsgRemoveMarketsResponse); } // MsgUpsertMarkets defines a message carrying a payload for performing market @@ -134,3 +139,23 @@ message MsgRemoveMarketAuthorities { // MsgRemoveMarketAuthoritiesResponse defines the // Msg/RemoveMarketAuthoritiesResponse response type. message MsgRemoveMarketAuthoritiesResponse {} + +// MsgRemoveMarkets defines the Msg/RemoveMarkets request type. It contains the +// new markets to be removed from the market map. +message MsgRemoveMarkets { + option (cosmos.msg.v1.signer) = "admin"; + + // Admin defines the authority that is the x/marketmap + // Admin account. This account is set in the module parameters. + string admin = 1 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; + + // Markets is the list of markets to remove. + repeated string markets = 2; +} + +// MsgRemoveMarketsResponse defines the +// Msg/MsgRemoveMarketsResponse response type. +message MsgRemoveMarketsResponse { + // DeletedMarkets is the list of markets that were removed. + repeated string deleted_markets = 1; +} diff --git a/tests/integration/connect_ccv_suite.go b/tests/integration/connect_ccv_suite.go index 514ca95f9..d70aa029d 100644 --- a/tests/integration/connect_ccv_suite.go +++ b/tests/integration/connect_ccv_suite.go @@ -44,7 +44,7 @@ func NewConnectCCVIntegrationSuite( func (s *ConnectCCVSuite) TestCCVAggregation() { ethusdc := connecttypes.NewCurrencyPair("ETH", "USDC") - s.Require().NoError(s.AddCurrencyPairs(s.chain, s.user, 3600, ethusdc)) + s.Require().NoError(s.AddCurrencyPairs(s.chain, s.user, 3600, enabledTicker(ethusdc))) cc, closeFn, err := GetChainGRPC(s.chain) s.Require().NoError(err) diff --git a/tests/integration/connect_setup.go b/tests/integration/connect_setup.go index 140e4e011..d346c01b4 100644 --- a/tests/integration/connect_setup.go +++ b/tests/integration/connect_setup.go @@ -305,6 +305,33 @@ func QueryCurrencyPair(chain *cosmos.CosmosChain, cp connecttypes.CurrencyPair, return res.Price, int64(res.Nonce), nil } +// QueryMarket queries a market from the market map. +func QueryMarket(chain *cosmos.CosmosChain, cp connecttypes.CurrencyPair) (mmtypes.Market, error) { + grpcAddr := chain.GetHostGRPCAddress() + + // create the client + cc, err := grpc.Dial(grpcAddr, grpc.WithTransportCredentials(insecure.NewCredentials())) + if err != nil { + return mmtypes.Market{}, err + } + defer cc.Close() + + // create the mm client + client := mmtypes.NewQueryClient(cc) + + ctx := context.Background() + + // query the currency pairs + res, err := client.Market(ctx, &mmtypes.MarketRequest{ + CurrencyPair: cp, + }) + if err != nil { + return mmtypes.Market{}, err + } + + return res.Market, nil +} + // SubmitProposal creates and submits a proposal to the chain func SubmitProposal(chain *cosmos.CosmosChain, deposit sdk.Coin, submitter string, msgs ...sdk.Msg) (string, error) { // build the proposal @@ -359,30 +386,26 @@ func PassProposal(chain *cosmos.CosmosChain, propId string, timeout time.Duratio // AddCurrencyPairs creates + submits the proposal to add the given currency-pairs to state, votes for the prop w/ all nodes, // and waits for the proposal to pass. -func (s *ConnectIntegrationSuite) AddCurrencyPairs(chain *cosmos.CosmosChain, user cosmos.User, price float64, cps ...connecttypes.CurrencyPair) error { - creates := make([]mmtypes.Market, len(cps)) - for i, cp := range cps { +func (s *ConnectIntegrationSuite) AddCurrencyPairs(chain *cosmos.CosmosChain, user cosmos.User, price float64, + tickers ...mmtypes.Ticker, +) error { + creates := make([]mmtypes.Market, len(tickers)) + for i, ticker := range tickers { creates[i] = mmtypes.Market{ - Ticker: mmtypes.Ticker{ - CurrencyPair: cp, - Decimals: 8, - MinProviderCount: 1, - Metadata_JSON: "", - Enabled: true, - }, + Ticker: ticker, ProviderConfigs: []mmtypes.ProviderConfig{ { Name: static.Name, - OffChainTicker: cp.String(), + OffChainTicker: ticker.String(), Metadata_JSON: fmt.Sprintf(`{"price": %f}`, price), }, }, } } - msg := &mmtypes.MsgCreateMarkets{ - Authority: s.user.FormattedAddress(), - CreateMarkets: creates, + msg := &mmtypes.MsgUpsertMarkets{ + Authority: s.user.FormattedAddress(), + Markets: creates, } tx := CreateTx(s.T(), s.chain, user, gasPrice, msg) @@ -403,6 +426,37 @@ func (s *ConnectIntegrationSuite) AddCurrencyPairs(chain *cosmos.CosmosChain, us return nil } +func (s *ConnectIntegrationSuite) RemoveMarket( + chain *cosmos.CosmosChain, + markets []connecttypes.CurrencyPair, +) error { + marketString := make([]string, len(markets)) + for i, market := range markets { + marketString[i] = market.String() + } + + msg := &mmtypes.MsgRemoveMarkets{ + Admin: s.user.FormattedAddress(), + Markets: marketString, + } + + tx := CreateTx(s.T(), s.chain, s.user, gasPrice, msg) + + // get an rpc endpoint for the chain + client := chain.Nodes()[0].Client + // broadcast the tx + resp, err := client.BroadcastTxCommit(context.Background(), tx) + if err != nil { + return err + } + + if resp.TxResult.Code != abcitypes.CodeTypeOK { + return fmt.Errorf(resp.TxResult.Log) + } + + return nil +} + func (s *ConnectIntegrationSuite) UpdateCurrencyPair(chain *cosmos.CosmosChain, markets []mmtypes.Market) error { msg := &mmtypes.MsgUpsertMarkets{ Authority: s.user.FormattedAddress(), @@ -451,7 +505,7 @@ func QueryProposal(chain *cosmos.CosmosChain, propID string) (*govtypesv1.QueryP }) } -// WaitForProposalStatus, waits for the deposit period for the proposal to end +// WaitForProposalStatus waits for the deposit period for the proposal to end func WaitForProposalStatus(chain *cosmos.CosmosChain, propID string, timeout time.Duration, status govtypesv1.ProposalStatus) error { return testutil.WaitForCondition(timeout, 1*time.Second, func() (bool, error) { prop, err := QueryProposal(chain, propID) diff --git a/tests/integration/connect_suite.go b/tests/integration/connect_suite.go index f71f20db3..b63f1d621 100644 --- a/tests/integration/connect_suite.go +++ b/tests/integration/connect_suite.go @@ -38,7 +38,6 @@ const ( defaultDenom = "stake" validatorKey = "validator" yes = "yes" - deposit = 1000000 userMnemonic = "foster poverty abstract scorpion short shrimp tilt edge romance adapt only benefit moral another where host egg echo ability wisdom lizard lazy pool roast" userAccountAddressHex = "877E307618AB73E009A978AC32E0264791F6D40A" gasPrice = 100 @@ -347,11 +346,11 @@ func (s *ConnectOracleIntegrationSuite) TestOracleModule() { // pass a governance proposal to approve a new currency-pair, and check Prices are reported s.Run("Add a currency-pair and check Prices", func() { - s.Require().NoError(s.AddCurrencyPairs(s.chain, s.user, 1.1, []connecttypes.CurrencyPair{ - { + s.Require().NoError(s.AddCurrencyPairs(s.chain, s.user, 1.1, []mmtypes.Ticker{ + enabledTicker(connecttypes.CurrencyPair{ Base: "BTC", Quote: "USD", - }, + }), }...)) // check that the currency-pair is added to state @@ -365,13 +364,51 @@ func (s *ConnectOracleIntegrationSuite) TestOracleModule() { s.Run("Add multiple Currency Pairs", func() { cp1 := connecttypes.NewCurrencyPair("ETH", "USD") cp2 := connecttypes.NewCurrencyPair("USDT", "USD") - s.Require().NoError(s.AddCurrencyPairs(s.chain, s.user, 1.1, []connecttypes.CurrencyPair{ - cp1, cp2, + s.Require().NoError(s.AddCurrencyPairs(s.chain, s.user, 1.1, []mmtypes.Ticker{ + enabledTicker(cp1), + enabledTicker(cp2), }...)) resp, err := QueryCurrencyPairs(s.chain) s.Require().NoError(err) s.Require().True(len(resp.CurrencyPairs) == 3) + + s.Run("fail to remove an enabled market", func() { + s.Require().Error(s.RemoveMarket(s.chain, []connecttypes.CurrencyPair{cp1})) + + // check not removed + market, err := QueryMarket(s.chain, cp1) + s.Require().NoError(err) + s.Require().NotNil(market) + }) + }) + + s.Run("remove a disabled market", func() { + disabledCP := connecttypes.NewCurrencyPair("DIS", "ABLE") + s.Require().NoError(s.AddCurrencyPairs(s.chain, s.user, 1.1, []mmtypes.Ticker{ + disabledTicker(disabledCP), + }...)) + + market, err := QueryMarket(s.chain, disabledCP) + s.Require().NoError(err) + s.Require().NotNil(market) + + s.Require().NoError(s.RemoveMarket(s.chain, []connecttypes.CurrencyPair{disabledCP})) + + // check removed + _, err = QueryMarket(s.chain, disabledCP) + s.Require().Error(err) + }) + + s.Run("remove a non existent market", func() { + nonexistentCP := connecttypes.NewCurrencyPair("NON", "EXIST") + + // check removed doesnt exist + _, err := QueryMarket(s.chain, nonexistentCP) + s.Require().Error(err) + + // tx will not error + s.Require().NoError(s.RemoveMarket(s.chain, []connecttypes.CurrencyPair{nonexistentCP})) }) } @@ -381,9 +418,16 @@ func translateGRPCAddr(chain *cosmos.CosmosChain) string { func (s *ConnectOracleIntegrationSuite) TestNodeFailures() { ethusdcCP := connecttypes.NewCurrencyPair("ETH", "USDC") + tickerETHUSDC := mmtypes.Ticker{ + CurrencyPair: ethusdcCP, + Decimals: 8, + MinProviderCount: 1, + Enabled: true, + Metadata_JSON: "", + } - s.Require().NoError(s.AddCurrencyPairs(s.chain, s.user, 1.1, []connecttypes.CurrencyPair{ - ethusdcCP, + s.Require().NoError(s.AddCurrencyPairs(s.chain, s.user, 1.1, []mmtypes.Ticker{ + tickerETHUSDC, }...)) cc, closeFn, err := GetChainGRPC(s.chain) @@ -577,19 +621,39 @@ func (s *ConnectOracleIntegrationSuite) TestNodeFailures() { }) } +func enabledTicker(pair connecttypes.CurrencyPair) mmtypes.Ticker { + return mmtypes.Ticker{ + CurrencyPair: pair, + Decimals: 8, + MinProviderCount: 1, + Enabled: true, + Metadata_JSON: "", + } +} + +func disabledTicker(pair connecttypes.CurrencyPair) mmtypes.Ticker { + return mmtypes.Ticker{ + CurrencyPair: pair, + Decimals: 8, + MinProviderCount: 1, + Enabled: false, + Metadata_JSON: "", + } +} + func (s *ConnectOracleIntegrationSuite) TestMultiplePriceFeeds() { ethusdcCP := connecttypes.NewCurrencyPair("ETH", "USDC") ethusdtCP := connecttypes.NewCurrencyPair("ETH", "USDT") ethusdCP := connecttypes.NewCurrencyPair("ETH", "USD") - // add multiple currency pairs - cps := []connecttypes.CurrencyPair{ - ethusdcCP, - ethusdtCP, - ethusdCP, + // add multiple tickers + tickers := []mmtypes.Ticker{ + enabledTicker(ethusdcCP), + enabledTicker(ethusdtCP), + enabledTicker(ethusdCP), } - s.Require().NoError(s.AddCurrencyPairs(s.chain, s.user, 1.1, cps...)) + s.Require().NoError(s.AddCurrencyPairs(s.chain, s.user, 1.1, tickers...)) cc, closeFn, err := GetChainGRPC(s.chain) s.Require().NoError(err) @@ -671,8 +735,8 @@ func (s *ConnectOracleIntegrationSuite) TestMultiplePriceFeeds() { s.Require().NoError(err) // query for the given currency pair - for _, cp := range cps { - resp, _, err := QueryCurrencyPair(s.chain, cp, height) + for _, ticker := range tickers { + resp, _, err := QueryCurrencyPair(s.chain, ticker.CurrencyPair, height) s.Require().NoError(err) s.Require().Equal(int64(110000000), resp.Price.Int64()) } @@ -739,8 +803,8 @@ func (s *ConnectOracleIntegrationSuite) TestMultiplePriceFeeds() { s.Require().NoError(err) // query for the given currency pair - for _, cp := range cps { - resp, _, err := QueryCurrencyPair(s.chain, cp, height) + for _, ticker := range tickers { + resp, _, err := QueryCurrencyPair(s.chain, ticker.CurrencyPair, height) s.Require().NoError(err) s.Require().Equal(int64(110000000), resp.Price.Int64()) } diff --git a/tests/integration/connect_validator_suite.go b/tests/integration/connect_validator_suite.go index e56ff4fb1..77757a1af 100644 --- a/tests/integration/connect_validator_suite.go +++ b/tests/integration/connect_validator_suite.go @@ -10,6 +10,7 @@ import ( "github.com/skip-mev/connect/v2/oracle/types" connecttypes "github.com/skip-mev/connect/v2/pkg/types" "github.com/skip-mev/connect/v2/providers/static" + mmtypes "github.com/skip-mev/connect/v2/x/marketmap/types" oracletypes "github.com/skip-mev/connect/v2/x/oracle/types" ) @@ -30,13 +31,13 @@ func (s *ConnectOracleValidatorIntegrationSuite) TestUnbonding() { ethusdCP := connecttypes.NewCurrencyPair("ETH", "USD") // add multiple currency pairs - cps := []connecttypes.CurrencyPair{ - ethusdcCP, - ethusdtCP, - ethusdCP, + tickers := []mmtypes.Ticker{ + enabledTicker(ethusdcCP), + enabledTicker(ethusdtCP), + enabledTicker(ethusdCP), } - s.Require().NoError(s.AddCurrencyPairs(s.chain, s.user, 1.1, cps...)) + s.Require().NoError(s.AddCurrencyPairs(s.chain, s.user, 1.1, tickers...)) cc, closeFn, err := GetChainGRPC(s.chain) s.Require().NoError(err) diff --git a/tests/integration/consumer.go b/tests/integration/consumer.go index 42e3889c7..5c9b12130 100644 --- a/tests/integration/consumer.go +++ b/tests/integration/consumer.go @@ -16,7 +16,7 @@ import ( var ( providerChainID = "provider-1" - providerNumValidators = int(4) + providerNumValidators = 4 providerVersion = "v5.0.0-rc0" ) diff --git a/x/marketmap/keeper/keeper.go b/x/marketmap/keeper/keeper.go index ba9a6f4e8..2abfb7253 100644 --- a/x/marketmap/keeper/keeper.go +++ b/x/marketmap/keeper/keeper.go @@ -2,6 +2,7 @@ package keeper import ( "context" + "errors" "fmt" "cosmossdk.io/collections" @@ -31,10 +32,13 @@ type Keeper struct { // params is the module's parameters. params collections.Item[types.Params] + + // deleteValidationHooks are called by the keeper before any deletion call is performed. + deleteMarketValidationHooks types.MarketValidationHooks } // NewKeeper initializes the keeper and its backing stores. -func NewKeeper(ss store.KVStoreService, cdc codec.BinaryCodec, authority sdk.AccAddress) *Keeper { +func NewKeeper(ss store.KVStoreService, cdc codec.BinaryCodec, authority sdk.AccAddress, opts ...Option) *Keeper { sb := collections.NewSchemaBuilder(ss) // Create the collections item that will track the module parameters. @@ -45,14 +49,27 @@ func NewKeeper(ss store.KVStoreService, cdc codec.BinaryCodec, authority sdk.Acc codec.CollValue[types.Params](cdc), ) - return &Keeper{ - cdc: cdc, - authority: authority, - markets: collections.NewMap(sb, types.MarketsPrefix, "markets", types.TickersCodec, codec.CollValue[types.Market](cdc)), - lastUpdated: collections.NewItem[uint64](sb, types.LastUpdatedPrefix, "last_updated", types.LastUpdatedCodec), - params: params, - hooks: &types.NoopMarketMapHooks{}, + k := &Keeper{ + cdc: cdc, + authority: authority, + markets: collections.NewMap(sb, types.MarketsPrefix, "markets", types.TickersCodec, codec.CollValue[types.Market](cdc)), + lastUpdated: collections.NewItem[uint64](sb, types.LastUpdatedPrefix, "last_updated", types.LastUpdatedCodec), + params: params, + hooks: &types.NoopMarketMapHooks{}, + deleteMarketValidationHooks: types.DefaultDeleteMarketValidationHooks(), + } + + // apply options to default initialized keeper + for _, opt := range opts { + opt(k) } + + return k +} + +// SetDeleteMarketValidationHooks sets the MarketValidationHooks for deletion in the keeper. +func (k *Keeper) SetDeleteMarketValidationHooks(hooks types.MarketValidationHooks) { + k.deleteMarketValidationHooks = hooks } // SetLastUpdated sets the lastUpdated field to the current block height. @@ -110,7 +127,6 @@ func (k *Keeper) GetAllMarkets(ctx context.Context) (map[string]types.Market, er if err != nil { return nil, err } - m := make(map[string]types.Market, len(keyValues)) for _, keyValue := range keyValues { m[string(keyValue.Key)] = keyValue.Value @@ -135,7 +151,7 @@ func (k *Keeper) CreateMarket(ctx context.Context, market types.Market) error { } // UpdateMarket updates a Market. -// The Ticker.String corresponds to a market, and exist unique. +// The Ticker.String corresponds to a market, and exists uniquely. func (k *Keeper) UpdateMarket(ctx context.Context, market types.Market) error { // Check if Ticker already exists for the provider alreadyExists, err := k.markets.Has(ctx, types.TickerString(market.Ticker.String())) @@ -149,19 +165,28 @@ func (k *Keeper) UpdateMarket(ctx context.Context, market types.Market) error { return k.setMarket(ctx, market) } -// DeleteMarket removes a Market. -// This is currently only expected to be called in upgrade handlers, and callers will need to separately call -// RemoveCurrencyPair on x/oracle to clean up leftover state in that module. -func (k *Keeper) DeleteMarket(ctx context.Context, tickerStr string) error { - // Check if Ticker exists - alreadyExists, err := k.markets.Has(ctx, types.TickerString(tickerStr)) - if err != nil { - return err +// DeleteMarket removes a Market. If the market does not exist, this is a no-op and nil is returned. +// If the market exists, all DeleteMarketValidationHooks are called on the market before deletion. +// Additionally, returns true if the market was deleted. +func (k *Keeper) DeleteMarket(ctx context.Context, tickerStr string) (bool, error) { + market, err := k.GetMarket(ctx, tickerStr) + switch { + case errors.Is(err, collections.ErrNotFound): + return false, nil + case err != nil: + return false, fmt.Errorf("failed to get market for ticker %s: %w", tickerStr, err) } - if !alreadyExists { - return types.NewMarketDoesNotExistsError(types.TickerString(tickerStr)) + + if err := k.deleteMarketValidationHooks.ValidateMarket(ctx, market); err != nil { + return false, err } - return k.markets.Remove(ctx, types.TickerString(tickerStr)) + + err = k.markets.Remove(ctx, types.TickerString(market.Ticker.String())) + if err != nil { + return false, err + } + + return true, nil } // HasMarket checks if a market exists in the store. diff --git a/x/marketmap/keeper/keeper_test.go b/x/marketmap/keeper/keeper_test.go index e624b92a9..118d311e0 100644 --- a/x/marketmap/keeper/keeper_test.go +++ b/x/marketmap/keeper/keeper_test.go @@ -323,14 +323,30 @@ func (s *KeeperTestSuite) TestInvalidCreateDisabledNormalizeBy() { func (s *KeeperTestSuite) TestDeleteMarket() { // create a valid markets - s.Require().NoError(s.keeper.CreateMarket(s.ctx, btcusdt)) + btcCopy := btcusdt + btcCopy.Ticker.Enabled = true + s.Require().NoError(s.keeper.CreateMarket(s.ctx, btcCopy)) + + // invalid delete will return nil - idempotent + deleted, err := s.keeper.DeleteMarket(s.ctx, "foobar") + s.Require().NoError(err) + s.Require().False(deleted) - // invalid delete fails - s.Require().Error(s.keeper.DeleteMarket(s.ctx, "foobar")) + // cannot delete enabled markets + deleted, err = s.keeper.DeleteMarket(s.ctx, btcCopy.Ticker.String()) + s.Require().Error(err) + s.Require().False(deleted) + + // disable market + btcCopy.Ticker.Enabled = false + s.Require().NoError(s.keeper.UpdateMarket(s.ctx, btcCopy)) + + // delete disabled markets + deleted, err = s.keeper.DeleteMarket(s.ctx, btcCopy.Ticker.String()) + s.Require().NoError(err) + s.Require().True(deleted) - // valid delete works - s.Require().NoError(s.keeper.DeleteMarket(s.ctx, btcusdt.Ticker.String())) - _, err := s.keeper.GetMarket(s.ctx, btcusdt.Ticker.String()) + _, err = s.keeper.GetMarket(s.ctx, btcCopy.Ticker.String()) s.Require().Error(err) } diff --git a/x/marketmap/keeper/msg_server.go b/x/marketmap/keeper/msg_server.go index 044a07c5e..960bfdf6b 100644 --- a/x/marketmap/keeper/msg_server.go +++ b/x/marketmap/keeper/msg_server.go @@ -250,6 +250,57 @@ func (ms msgServer) RemoveMarketAuthorities(goCtx context.Context, msg *types.Ms return &types.MsgRemoveMarketAuthoritiesResponse{}, nil } +// RemoveMarkets attempts to remove the provided markets from the MarketMap. Stateful validation is performed on these +// markets using the configured ValidationHooks. +func (ms msgServer) RemoveMarkets( + goCtx context.Context, + msg *types.MsgRemoveMarkets) ( + *types.MsgRemoveMarketsResponse, error, +) { + if msg == nil { + return nil, fmt.Errorf("unable to process nil msg") + } + + ctx := sdk.UnwrapSDKContext(goCtx) + + params, err := ms.k.GetParams(ctx) + if err != nil { + return nil, err + } + + if msg.Admin != params.Admin { + return nil, fmt.Errorf("request admin %s does not match module admin %s", msg.Admin, params.Admin) + } + + deletedMarkets := make([]string, 0, len(msg.Markets)) + for _, market := range msg.Markets { + deleted, err := ms.k.DeleteMarket(ctx, market) + if err != nil { + return nil, fmt.Errorf("unable to delete market: %w", err) + } + + if deleted { + ctx.Logger().Info(fmt.Sprintf("deleted market %s", market)) + deletedMarkets = append(deletedMarkets, market) + } + } + + // check if the resulting state is valid: it may not be valid if the removed market is used as a normalization pair + allMarkets, err := ms.k.GetAllMarkets(ctx) + if err != nil { + return nil, err + } + + mm := types.MarketMap{Markets: allMarkets} + if err := mm.ValidateBasic(); err != nil { + return nil, fmt.Errorf("invalid state resulting from removals: %w", err) + } + + return &types.MsgRemoveMarketsResponse{ + DeletedMarkets: deletedMarkets, + }, nil +} + // checkMarketAuthority checks if the given authority is the x/marketmap's list of MarketAuthorities. func checkMarketAuthority(authority string, params types.Params) bool { if len(params.MarketAuthorities) == 0 { diff --git a/x/marketmap/keeper/msg_server_test.go b/x/marketmap/keeper/msg_server_test.go index 6c47d8c5b..6ee63330a 100644 --- a/x/marketmap/keeper/msg_server_test.go +++ b/x/marketmap/keeper/msg_server_test.go @@ -519,3 +519,214 @@ func (s *KeeperTestSuite) TestMsgServerUpsertMarkets() { s.Require().Nil(resp) }) } + +func (s *KeeperTestSuite) TestMsgServerRemoveMarkets() { + msgServer := keeper.NewMsgServer(s.keeper) + + s.Run("unable to process nil request", func() { + resp, err := msgServer.RemoveMarkets(s.ctx, nil) + s.Require().Error(err) + s.Require().Nil(resp) + }) + + s.Run("unable to process for invalid authority", func() { + msg := &types.MsgRemoveMarkets{ + Admin: "invalid", + } + resp, err := msgServer.RemoveMarkets(s.ctx, msg) + s.Require().Error(err) + s.Require().Nil(resp) + }) + + s.Run("only remove existing markets - no error", func() { + msg := &types.MsgRemoveMarkets{ + Admin: s.admin, + Markets: []string{"BTC/USD", "ETH/USDT"}, + } + resp, err := msgServer.RemoveMarkets(s.ctx, msg) + s.Require().NoError(err) + s.Require().Equal([]string{}, resp.DeletedMarkets) + }) + + s.Run("unable to remove non-existent market - single", func() { + msg := &types.MsgRemoveMarkets{ + Admin: s.admin, + Markets: []string{"BTC/USD"}, + } + resp, err := msgServer.RemoveMarkets(s.ctx, msg) + s.Require().NoError(err) + s.Require().Equal([]string{}, resp.DeletedMarkets) + }) + + s.Run("able to remove disabled market", func() { + copyBTC := btcusdt + copyBTC.Ticker.Enabled = false + + msg := &types.MsgRemoveMarkets{ + Admin: s.admin, + Markets: []string{copyBTC.Ticker.String()}, + } + + err := s.keeper.CreateMarket(s.ctx, copyBTC) + s.Require().NoError(err) + + resp, err := msgServer.RemoveMarkets(s.ctx, msg) + s.Require().NoError(err) + s.Require().Equal([]string{copyBTC.Ticker.String()}, resp.DeletedMarkets) + + // market should not exist + _, err = s.keeper.GetMarket(s.ctx, copyBTC.Ticker.String()) + s.Require().Error(err) + }) + + s.Run("do not remove enabled market", func() { + copyBTC := btcusdt + copyBTC.Ticker.Enabled = true + + err := s.keeper.CreateMarket(s.ctx, copyBTC) + s.Require().NoError(err) + + msg := &types.MsgRemoveMarkets{ + Admin: s.admin, + Markets: []string{copyBTC.Ticker.String()}, + } + + resp, err := msgServer.RemoveMarkets(s.ctx, msg) + s.Require().Error(err) + s.Require().Nil(resp) + + // market should exist + _, err = s.keeper.GetMarket(s.ctx, copyBTC.Ticker.String()) + s.Require().NoError(err) + + // update market to be disabled + copyBTC.Ticker.Enabled = false + + err = s.keeper.UpdateMarket(s.ctx, copyBTC) + s.Require().NoError(err) + + // remove + resp, err = msgServer.RemoveMarkets(s.ctx, msg) + s.Require().NoError(err) + s.Require().Equal([]string{copyBTC.Ticker.String()}, resp.DeletedMarkets) + + // market should not exist + _, err = s.keeper.GetMarket(s.ctx, copyBTC.Ticker.String()) + s.Require().Error(err) + }) + + s.Run("resulting state is invalid - 1", func() { + // add a market that depends on the btc market + copyBTC := btcusdt + + err := s.keeper.CreateMarket(s.ctx, copyBTC) + s.Require().NoError(err) + + copyETH := ethusdt + copyETH.ProviderConfigs = []types.ProviderConfig{ + { + Name: "normalized", + OffChainTicker: "normalized", + NormalizeByPair: &connecttypes.CurrencyPair{ + Base: copyBTC.Ticker.CurrencyPair.Base, + Quote: copyBTC.Ticker.CurrencyPair.Quote, + }, + }, + } + + err = s.keeper.CreateMarket(s.ctx, copyETH) + s.Require().NoError(err) + + msgRemoveBTC := &types.MsgRemoveMarkets{ + Admin: s.admin, + Markets: []string{copyBTC.Ticker.String()}, + } + + msgRemoveETH := &types.MsgRemoveMarkets{ + Admin: s.admin, + Markets: []string{copyETH.Ticker.String()}, + } + + resp, err := msgServer.RemoveMarkets(s.ctx, msgRemoveBTC) + s.Require().Error(err) + s.Require().Nil(resp) + + // remove dependent market first for valid state in 2 transaction + resp, err = msgServer.RemoveMarkets(s.ctx, msgRemoveETH) + s.Require().NoError(err) + s.Require().NotNil(resp) + + // market should not exist + _, err = s.keeper.GetMarket(s.ctx, copyETH.Ticker.String()) + s.Require().Error(err) + }) + + s.Run("remove both markets in one tx - no dependency", func() { + // add a market that depends on the btc market + copyBTC := btcusdt + copyETH := ethusdt + + err := s.keeper.CreateMarket(s.ctx, copyBTC) + s.Require().NoError(err) + + err = s.keeper.CreateMarket(s.ctx, copyETH) + s.Require().NoError(err) + + msg := &types.MsgRemoveMarkets{ + Admin: s.admin, + Markets: []string{copyBTC.Ticker.String(), copyETH.Ticker.String()}, + } + + resp, err := msgServer.RemoveMarkets(s.ctx, msg) + s.Require().NoError(err) + s.Require().NotNil(resp) + + // market should not exist + _, err = s.keeper.GetMarket(s.ctx, copyBTC.Ticker.String()) + s.Require().Error(err) + + // market should not exist + _, err = s.keeper.GetMarket(s.ctx, copyETH.Ticker.String()) + s.Require().Error(err) + }) + + s.Run("remove both markets in one tx - with dependency", func() { + // add a market that depends on the btc market + copyBTC := btcusdt + + err := s.keeper.CreateMarket(s.ctx, copyBTC) + s.Require().NoError(err) + + copyETH := ethusdt + copyETH.ProviderConfigs = []types.ProviderConfig{ + { + Name: "normalized", + OffChainTicker: "normalized", + NormalizeByPair: &connecttypes.CurrencyPair{ + Base: copyBTC.Ticker.CurrencyPair.Base, + Quote: copyBTC.Ticker.CurrencyPair.Quote, + }, + }, + } + + err = s.keeper.CreateMarket(s.ctx, copyETH) + s.Require().NoError(err) + + msg := &types.MsgRemoveMarkets{ + Admin: s.admin, + Markets: []string{copyBTC.Ticker.String(), copyETH.Ticker.String()}, + } + + resp, err := msgServer.RemoveMarkets(s.ctx, msg) + s.Require().NoError(err) + s.Require().NotNil(resp) + + // market should not exist + _, err = s.keeper.GetMarket(s.ctx, copyBTC.Ticker.String()) + s.Require().Error(err) + + // market should not exist + _, err = s.keeper.GetMarket(s.ctx, copyETH.Ticker.String()) + s.Require().Error(err) + }) +} diff --git a/x/marketmap/keeper/options.go b/x/marketmap/keeper/options.go new file mode 100644 index 000000000..112eaa764 --- /dev/null +++ b/x/marketmap/keeper/options.go @@ -0,0 +1,21 @@ +package keeper + +import "github.com/skip-mev/connect/v2/x/marketmap/types" + +// Option is a type that modifies a keeper during instantiation. These can be passed variadically into NewKeeper +// to specify keeper behavior. +type Option func(*Keeper) + +// WithHooks sets the keeper hooks to the given hooks. +func WithHooks(hooks types.MarketMapHooks) Option { + return func(k *Keeper) { + k.hooks = hooks + } +} + +// WithDeleteValidationHooks sets the keeper deleteMarketValidationHooks to the given hooks. +func WithDeleteValidationHooks(hooks []types.MarketValidationHook) Option { + return func(k *Keeper) { + k.deleteMarketValidationHooks = hooks + } +} diff --git a/x/marketmap/keeper/validation_hooks.go b/x/marketmap/keeper/validation_hooks.go new file mode 100644 index 000000000..b55569d4a --- /dev/null +++ b/x/marketmap/keeper/validation_hooks.go @@ -0,0 +1 @@ +package keeper diff --git a/x/marketmap/types/codec.go b/x/marketmap/types/codec.go index 00e2460f1..6fbb6fcdd 100644 --- a/x/marketmap/types/codec.go +++ b/x/marketmap/types/codec.go @@ -15,6 +15,8 @@ func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { legacy.RegisterAminoMsg(cdc, &MsgCreateMarkets{}, "connect/x/marketmap/MsgCreateMarkets") legacy.RegisterAminoMsg(cdc, &MsgUpdateMarkets{}, "connect/x/marketmap/MsgUpdateMarkets") legacy.RegisterAminoMsg(cdc, &MsgParams{}, "connect/x/marketmap/MsgParams") + legacy.RegisterAminoMsg(cdc, &MsgUpsertMarkets{}, "connect/x/marketmap/MsgUpsertMarkets") + legacy.RegisterAminoMsg(cdc, &MsgRemoveMarkets{}, "connect/x/marketmap/MsgRemoveMarkets") } // RegisterInterfaces registers the x/marketmap messages + message service w/ the InterfaceRegistry (registry). @@ -24,6 +26,9 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) { &MsgCreateMarkets{}, &MsgUpdateMarkets{}, &MsgParams{}, + &MsgUpsertMarkets{}, + &MsgRemoveMarkets{}, + &MsgRemoveMarketAuthorities{}, ) msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) diff --git a/x/marketmap/types/errors.go b/x/marketmap/types/errors.go index effcebcf3..a14f47e84 100644 --- a/x/marketmap/types/errors.go +++ b/x/marketmap/types/errors.go @@ -29,3 +29,17 @@ func NewMarketDoesNotExistsError(ticker TickerString) MarketDoesNotExistsError { func (e MarketDoesNotExistsError) Error() string { return fmt.Sprintf("market does not exist for ticker %s", e.ticker) } + +// MarketIsEnabledError is an error indicating the given Market does not exist in state. +type MarketIsEnabledError struct { + ticker TickerString +} + +func NewMarketIsEnabledError(ticker TickerString) MarketIsEnabledError { + return MarketIsEnabledError{ticker: ticker} +} + +// Error returns the error string for MarketIsEnabledError. +func (e MarketIsEnabledError) Error() string { + return fmt.Sprintf("market is currently enabled %s", e.ticker) +} diff --git a/x/marketmap/types/hooks.go b/x/marketmap/types/hooks.go index 541e3e30f..90b70c769 100644 --- a/x/marketmap/types/hooks.go +++ b/x/marketmap/types/hooks.go @@ -14,6 +14,9 @@ type MarketMapHooks interface { // AfterMarketGenesis is called after x/marketmap init genesis. AfterMarketGenesis(ctx sdk.Context, tickers map[string]Market) error + + // AfterMarketRemoved is called after a market is removed. + AfterMarketRemoved(ctx sdk.Context, market Market) error } var _ MarketMapHooks = &MultiMarketMapHooks{} @@ -54,6 +57,17 @@ func (mh MultiMarketMapHooks) AfterMarketGenesis(ctx sdk.Context, markets map[st return nil } +// AfterMarketRemoved calls all AfterMarketRemoved hooks registered to the MultiMarketMapHooks. +func (mh MultiMarketMapHooks) AfterMarketRemoved(ctx sdk.Context, market Market) error { + for i := range mh { + if err := mh[i].AfterMarketRemoved(ctx, market); err != nil { + return err + } + } + + return nil +} + // MarketMapHooksWrapper is a wrapper for modules to inject MarketMapHooks using depinject. type MarketMapHooksWrapper struct{ MarketMapHooks } @@ -73,3 +87,7 @@ func (n *NoopMarketMapHooks) AfterMarketUpdated(_ sdk.Context, _ Market) error { func (n *NoopMarketMapHooks) AfterMarketGenesis(_ sdk.Context, _ map[string]Market) error { return nil } + +func (n *NoopMarketMapHooks) AfterMarketRemoved(_ sdk.Context, _ Market) error { + return nil +} diff --git a/x/marketmap/types/mocks/MarketMapHooks.go b/x/marketmap/types/mocks/MarketMapHooks.go index d001659af..20661e446 100644 --- a/x/marketmap/types/mocks/MarketMapHooks.go +++ b/x/marketmap/types/mocks/MarketMapHooks.go @@ -117,6 +117,53 @@ func (_c *MarketMapHooks_AfterMarketGenesis_Call) RunAndReturn(run func(types.Co return _c } +// AfterMarketRemoved provides a mock function with given fields: ctx, market +func (_m *MarketMapHooks) AfterMarketRemoved(ctx types.Context, market marketmaptypes.Market) error { + ret := _m.Called(ctx, market) + + if len(ret) == 0 { + panic("no return value specified for AfterMarketRemoved") + } + + var r0 error + if rf, ok := ret.Get(0).(func(types.Context, marketmaptypes.Market) error); ok { + r0 = rf(ctx, market) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// MarketMapHooks_AfterMarketRemoved_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AfterMarketRemoved' +type MarketMapHooks_AfterMarketRemoved_Call struct { + *mock.Call +} + +// AfterMarketRemoved is a helper method to define mock.On call +// - ctx types.Context +// - market marketmaptypes.Market +func (_e *MarketMapHooks_Expecter) AfterMarketRemoved(ctx interface{}, market interface{}) *MarketMapHooks_AfterMarketRemoved_Call { + return &MarketMapHooks_AfterMarketRemoved_Call{Call: _e.mock.On("AfterMarketRemoved", ctx, market)} +} + +func (_c *MarketMapHooks_AfterMarketRemoved_Call) Run(run func(ctx types.Context, market marketmaptypes.Market)) *MarketMapHooks_AfterMarketRemoved_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Context), args[1].(marketmaptypes.Market)) + }) + return _c +} + +func (_c *MarketMapHooks_AfterMarketRemoved_Call) Return(_a0 error) *MarketMapHooks_AfterMarketRemoved_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *MarketMapHooks_AfterMarketRemoved_Call) RunAndReturn(run func(types.Context, marketmaptypes.Market) error) *MarketMapHooks_AfterMarketRemoved_Call { + _c.Call.Return(run) + return _c +} + // AfterMarketUpdated provides a mock function with given fields: ctx, market func (_m *MarketMapHooks) AfterMarketUpdated(ctx types.Context, market marketmaptypes.Market) error { ret := _m.Called(ctx, market) diff --git a/x/marketmap/types/msg.go b/x/marketmap/types/msg.go index 3f64dd570..bb3621da6 100644 --- a/x/marketmap/types/msg.go +++ b/x/marketmap/types/msg.go @@ -3,6 +3,8 @@ package types import ( "fmt" + connecttypes "github.com/skip-mev/connect/v2/pkg/types" + sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -12,6 +14,7 @@ var ( _ sdk.Msg = &MsgParams{} _ sdk.Msg = &MsgRemoveMarketAuthorities{} _ sdk.Msg = &MsgUpsertMarkets{} + _ sdk.Msg = &MsgRemoveMarkets{} ) // ValidateBasic asserts that the authority address in the upsert-markets message is formatted correctly. @@ -124,3 +127,31 @@ func (m *MsgRemoveMarketAuthorities) ValidateBasic() error { return nil } + +// ValidateBasic determines whether the information in the message is formatted correctly, specifically +// whether the signer is a valid acc-address. +func (m *MsgRemoveMarkets) ValidateBasic() error { + // validate signer address + if _, err := sdk.AccAddressFromBech32(m.Admin); err != nil { + return err + } + + if len(m.Markets) == 0 { + return fmt.Errorf("markets to remove cannot be nil") + } + + seenMarkets := make(map[string]struct{}, len(m.Markets)) + for _, market := range m.Markets { + if _, seen := seenMarkets[market]; seen { + return fmt.Errorf("duplicate market %s found", market) + } + + if _, err := connecttypes.CurrencyPairFromString(market); err != nil { + return fmt.Errorf("invalid market pair string: %w", err) + } + + seenMarkets[market] = struct{}{} + } + + return nil +} diff --git a/x/marketmap/types/msg_test.go b/x/marketmap/types/msg_test.go index fc22c2887..511c489d5 100644 --- a/x/marketmap/types/msg_test.go +++ b/x/marketmap/types/msg_test.go @@ -516,3 +516,64 @@ func TestValidateBasicMsgRemoveMarketAuthorities(t *testing.T) { }) } } + +func TestValidateBasicMsgRemoveMarkets(t *testing.T) { + rng := sample.Rand() + + tcs := []struct { + name string + msg types.MsgRemoveMarkets + expectPass bool + }{ + { + "if the Authority is not an acc-address - fail", + types.MsgRemoveMarkets{ + Admin: "invalid", + }, + false, + }, + { + name: "invalid message (no markets) - fail", + msg: types.MsgRemoveMarkets{ + Markets: nil, + Admin: sample.Address(rng), + }, + expectPass: false, + }, + { + name: "valid message - single market", + msg: types.MsgRemoveMarkets{ + Markets: []string{"USDT/USD"}, + Admin: sample.Address(rng), + }, + expectPass: true, + }, + { + name: "valid message - multiple markets", + msg: types.MsgRemoveMarkets{ + Markets: []string{"USDT/USD", "ETH/USD"}, + Admin: sample.Address(rng), + }, + expectPass: true, + }, + { + name: "invalid message (duplicate markets", + msg: types.MsgRemoveMarkets{ + Markets: []string{"USDT/USD", "USDT/USD"}, + Admin: sample.Address(rng), + }, + expectPass: false, + }, + } + + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + err := tc.msg.ValidateBasic() + if !tc.expectPass { + require.NotNil(t, err) + } else { + require.Nil(t, err) + } + }) + } +} diff --git a/x/marketmap/types/tx.pb.go b/x/marketmap/types/tx.pb.go index 4ac98b190..f4fd87c57 100644 --- a/x/marketmap/types/tx.pb.go +++ b/x/marketmap/types/tx.pb.go @@ -516,6 +516,110 @@ func (m *MsgRemoveMarketAuthoritiesResponse) XXX_DiscardUnknown() { var xxx_messageInfo_MsgRemoveMarketAuthoritiesResponse proto.InternalMessageInfo +// MsgRemoveMarkets defines the Msg/RemoveMarkets request type. It contains the +// new markets to be removed from the market map. +type MsgRemoveMarkets struct { + // Admin defines the authority that is the x/marketmap + // Admin account. This account is set in the module parameters. + Admin string `protobuf:"bytes,1,opt,name=admin,proto3" json:"admin,omitempty"` + // Markets is the list of markets to remove. + Markets []string `protobuf:"bytes,2,rep,name=markets,proto3" json:"markets,omitempty"` +} + +func (m *MsgRemoveMarkets) Reset() { *m = MsgRemoveMarkets{} } +func (m *MsgRemoveMarkets) String() string { return proto.CompactTextString(m) } +func (*MsgRemoveMarkets) ProtoMessage() {} +func (*MsgRemoveMarkets) Descriptor() ([]byte, []int) { + return fileDescriptor_37df9476ca9a2f81, []int{10} +} +func (m *MsgRemoveMarkets) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgRemoveMarkets) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgRemoveMarkets.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 *MsgRemoveMarkets) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgRemoveMarkets.Merge(m, src) +} +func (m *MsgRemoveMarkets) XXX_Size() int { + return m.Size() +} +func (m *MsgRemoveMarkets) XXX_DiscardUnknown() { + xxx_messageInfo_MsgRemoveMarkets.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgRemoveMarkets proto.InternalMessageInfo + +func (m *MsgRemoveMarkets) GetAdmin() string { + if m != nil { + return m.Admin + } + return "" +} + +func (m *MsgRemoveMarkets) GetMarkets() []string { + if m != nil { + return m.Markets + } + return nil +} + +// MsgRemoveMarketsResponse defines the +// Msg/MsgRemoveMarketsResponse response type. +type MsgRemoveMarketsResponse struct { + // DeletedMarkets is the list of markets that were removed. + DeletedMarkets []string `protobuf:"bytes,1,rep,name=deleted_markets,json=deletedMarkets,proto3" json:"deleted_markets,omitempty"` +} + +func (m *MsgRemoveMarketsResponse) Reset() { *m = MsgRemoveMarketsResponse{} } +func (m *MsgRemoveMarketsResponse) String() string { return proto.CompactTextString(m) } +func (*MsgRemoveMarketsResponse) ProtoMessage() {} +func (*MsgRemoveMarketsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_37df9476ca9a2f81, []int{11} +} +func (m *MsgRemoveMarketsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgRemoveMarketsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgRemoveMarketsResponse.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 *MsgRemoveMarketsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgRemoveMarketsResponse.Merge(m, src) +} +func (m *MsgRemoveMarketsResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgRemoveMarketsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgRemoveMarketsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgRemoveMarketsResponse proto.InternalMessageInfo + +func (m *MsgRemoveMarketsResponse) GetDeletedMarkets() []string { + if m != nil { + return m.DeletedMarkets + } + return nil +} + func init() { proto.RegisterType((*MsgUpsertMarkets)(nil), "connect.marketmap.v2.MsgUpsertMarkets") proto.RegisterType((*MsgUpsertMarketsResponse)(nil), "connect.marketmap.v2.MsgUpsertMarketsResponse") @@ -528,56 +632,61 @@ func init() { proto.RegisterType((*MsgParamsResponse)(nil), "connect.marketmap.v2.MsgParamsResponse") proto.RegisterType((*MsgRemoveMarketAuthorities)(nil), "connect.marketmap.v2.MsgRemoveMarketAuthorities") proto.RegisterType((*MsgRemoveMarketAuthoritiesResponse)(nil), "connect.marketmap.v2.MsgRemoveMarketAuthoritiesResponse") + proto.RegisterType((*MsgRemoveMarkets)(nil), "connect.marketmap.v2.MsgRemoveMarkets") + proto.RegisterType((*MsgRemoveMarketsResponse)(nil), "connect.marketmap.v2.MsgRemoveMarketsResponse") } func init() { proto.RegisterFile("connect/marketmap/v2/tx.proto", fileDescriptor_37df9476ca9a2f81) } var fileDescriptor_37df9476ca9a2f81 = []byte{ - // 690 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x55, 0xbf, 0x6f, 0xd3, 0x4e, - 0x14, 0xcf, 0xa5, 0x3f, 0xbe, 0xdf, 0x1c, 0xa4, 0xb4, 0x47, 0xa4, 0x1a, 0x0b, 0x9c, 0x62, 0x55, - 0xa5, 0x54, 0xaa, 0x5d, 0x82, 0x84, 0x2a, 0xc3, 0x40, 0x82, 0x18, 0x40, 0x8a, 0x84, 0x8c, 0x2a, - 0x21, 0x96, 0xc8, 0xb5, 0x4f, 0xae, 0xd5, 0xda, 0x67, 0xf9, 0x2e, 0x56, 0xbb, 0x21, 0x10, 0x0b, - 0x0b, 0x8c, 0x8c, 0x30, 0xb2, 0x75, 0xe0, 0x5f, 0x40, 0xea, 0x58, 0x75, 0x62, 0x42, 0xa8, 0x1d, - 0xca, 0x9f, 0x81, 0xe2, 0x3b, 0xbb, 0x71, 0x1b, 0xb7, 0x09, 0xb0, 0x24, 0x77, 0xef, 0x7d, 0xde, - 0xbb, 0xcf, 0xe7, 0xbd, 0x7b, 0x67, 0x78, 0xc3, 0x26, 0x41, 0x80, 0x6d, 0xa6, 0xfb, 0x56, 0xb4, - 0x89, 0x99, 0x6f, 0x85, 0x7a, 0xdc, 0xd0, 0xd9, 0xb6, 0x16, 0x46, 0x84, 0x11, 0x54, 0x13, 0x6e, - 0x2d, 0x73, 0x6b, 0x71, 0x43, 0x9e, 0xb5, 0x09, 0xf5, 0x09, 0xd5, 0x7d, 0xea, 0xea, 0xf1, 0x9d, - 0xde, 0x1f, 0x87, 0xcb, 0x35, 0x97, 0xb8, 0x24, 0x59, 0xea, 0xbd, 0x95, 0xb0, 0x5e, 0xe3, 0xf0, - 0x0e, 0x77, 0xf0, 0x8d, 0x70, 0xcd, 0x58, 0xbe, 0x17, 0x10, 0x3d, 0xf9, 0x15, 0xa6, 0x9b, 0x03, - 0x19, 0xf1, 0xcd, 0xb9, 0x90, 0xd0, 0x8a, 0x2c, 0x5f, 0x24, 0x56, 0xbf, 0x01, 0x38, 0xdd, 0xa6, - 0xee, 0x5a, 0x48, 0x71, 0xc4, 0xda, 0x09, 0x8c, 0xa2, 0x7b, 0xb0, 0x62, 0x75, 0xd9, 0x06, 0x89, - 0x3c, 0xb6, 0x23, 0x81, 0x39, 0xb0, 0x58, 0x69, 0x49, 0x07, 0x5f, 0x97, 0x6b, 0x82, 0x52, 0xd3, - 0x71, 0x22, 0x4c, 0xe9, 0x73, 0x16, 0x79, 0x81, 0x6b, 0x9e, 0x40, 0xd1, 0x03, 0xf8, 0x1f, 0x3f, - 0x89, 0x4a, 0xe5, 0xb9, 0xb1, 0xc5, 0x4b, 0x8d, 0xeb, 0xda, 0xa0, 0xba, 0x68, 0xfc, 0x9c, 0xd6, - 0xf8, 0xde, 0x8f, 0x7a, 0xc9, 0x4c, 0x43, 0x8c, 0xfb, 0xbf, 0x3e, 0xd5, 0x4b, 0xaf, 0x8f, 0x77, - 0x97, 0x4e, 0x32, 0xbe, 0x3b, 0xde, 0x5d, 0x9a, 0x4f, 0x45, 0x6c, 0xf7, 0xc9, 0x38, 0x4d, 0x59, - 0xdd, 0x07, 0x50, 0x3a, 0x6d, 0x34, 0x31, 0x0d, 0x49, 0x40, 0x31, 0xda, 0x82, 0x53, 0x3c, 0xb4, - 0xd3, 0x0d, 0x1d, 0x8b, 0x61, 0x2a, 0x81, 0x84, 0x5e, 0xb3, 0x80, 0x5e, 0x41, 0x1e, 0xc1, 0x7b, - 0x8d, 0xe7, 0x78, 0x1c, 0xb0, 0x68, 0xa7, 0x55, 0x96, 0x80, 0x59, 0xf5, 0xfb, 0xed, 0xf2, 0x43, - 0x88, 0xce, 0x02, 0xd1, 0x34, 0x1c, 0xdb, 0xc4, 0xa2, 0x9a, 0x66, 0x6f, 0x89, 0x6a, 0x70, 0x22, - 0xb6, 0xb6, 0xba, 0x58, 0x2a, 0xcf, 0x81, 0xc5, 0xff, 0x4d, 0xbe, 0x31, 0xca, 0xab, 0xc0, 0x18, - 0xff, 0xf8, 0xb9, 0x0e, 0xd4, 0x03, 0xde, 0x9a, 0x47, 0x11, 0xb6, 0x18, 0xfe, 0xdb, 0xd6, 0x3c, - 0x81, 0x53, 0x76, 0x92, 0xa8, 0x33, 0x7a, 0x87, 0xaa, 0x76, 0x3f, 0x85, 0x51, 0xfb, 0x94, 0xe3, - 0xaf, 0xca, 0x49, 0x9b, 0x72, 0xb6, 0xb4, 0xbc, 0xa9, 0x60, 0x5e, 0xb6, 0x7f, 0x20, 0x98, 0x37, - 0xfb, 0x4f, 0x04, 0x77, 0xfb, 0x29, 0x8c, 0x7e, 0x31, 0x9d, 0x33, 0x82, 0x73, 0xb6, 0x4c, 0xf0, - 0x7b, 0x00, 0x2b, 0x6d, 0xea, 0x3e, 0x4b, 0x06, 0x12, 0x19, 0x70, 0x92, 0x8f, 0x66, 0x22, 0xb3, - 0x90, 0x29, 0x47, 0x0b, 0xa6, 0x22, 0x22, 0x5f, 0xa5, 0xf2, 0xd0, 0x55, 0x32, 0xa6, 0xf2, 0xb2, - 0xd4, 0xab, 0x70, 0x26, 0x23, 0x94, 0xd1, 0x7c, 0x03, 0xa0, 0xdc, 0xa6, 0xae, 0x89, 0x7d, 0x12, - 0x0b, 0x0d, 0x4d, 0x11, 0xe1, 0x61, 0x8a, 0x6e, 0xc3, 0xe9, 0x28, 0x71, 0x75, 0x2c, 0x7e, 0x8c, - 0x98, 0xaf, 0x8a, 0x79, 0x85, 0xdb, 0x9b, 0xa9, 0x19, 0x69, 0x70, 0xc2, 0x72, 0x7c, 0x2f, 0xb8, - 0x90, 0x22, 0x87, 0x19, 0xb0, 0x47, 0x8f, 0xaf, 0xd5, 0x79, 0xa8, 0x16, 0x93, 0x48, 0xb9, 0x36, - 0xbe, 0x8c, 0xc3, 0xb1, 0x36, 0x75, 0x91, 0x0b, 0xab, 0xf9, 0xc1, 0x59, 0x28, 0x9c, 0xf5, 0x1c, - 0x4e, 0xd6, 0x86, 0xc3, 0x65, 0x6f, 0x8b, 0x0b, 0xab, 0xf9, 0x0b, 0xbb, 0x70, 0xce, 0xa3, 0xe2, - 0x0c, 0x75, 0xd0, 0xc0, 0xcb, 0x82, 0x5e, 0xc0, 0xcb, 0xdc, 0x21, 0xae, 0x4b, 0xbd, 0x30, 0x9e, - 0x03, 0xe4, 0x5b, 0x17, 0x00, 0xb2, 0xcc, 0x6f, 0x01, 0x9c, 0x2d, 0x6a, 0xee, 0x4a, 0x61, 0x92, - 0x82, 0x08, 0x79, 0x75, 0xd4, 0x88, 0x7c, 0x29, 0xfb, 0xbf, 0x43, 0x0b, 0xc3, 0xbd, 0xcf, 0xe7, - 0x96, 0x72, 0xc0, 0x3b, 0x2e, 0x4f, 0xbc, 0x3a, 0xde, 0x5d, 0x02, 0xad, 0xa7, 0x7b, 0x87, 0x0a, - 0xd8, 0x3f, 0x54, 0xc0, 0xcf, 0x43, 0x05, 0x7c, 0x38, 0x52, 0x4a, 0xfb, 0x47, 0x4a, 0xe9, 0xfb, - 0x91, 0x52, 0x7a, 0xb9, 0xe2, 0x7a, 0x6c, 0xa3, 0xbb, 0xae, 0xd9, 0xc4, 0xd7, 0xe9, 0xa6, 0x17, - 0x2e, 0xfb, 0x38, 0xd6, 0xd3, 0x71, 0x8f, 0x1b, 0xb9, 0x89, 0x67, 0x3b, 0x21, 0xa6, 0xeb, 0x93, - 0xc9, 0xe7, 0xf4, 0xee, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0x02, 0xbc, 0x2f, 0xbc, 0x28, 0x08, - 0x00, 0x00, + // 745 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0x4f, 0x4f, 0x13, 0x41, + 0x14, 0xef, 0x14, 0x8a, 0x76, 0xb4, 0x05, 0xc6, 0x26, 0xac, 0x1b, 0x6d, 0x71, 0x43, 0x0a, 0x92, + 0xb0, 0x8b, 0x35, 0x31, 0xa4, 0x7a, 0xb0, 0x25, 0x1e, 0x34, 0x69, 0x62, 0xd6, 0x90, 0x18, 0x2f, + 0xcd, 0xd2, 0x9d, 0x2c, 0x1b, 0xd8, 0x3f, 0xd9, 0x99, 0x6e, 0xe0, 0x66, 0x34, 0x5e, 0xbc, 0x68, + 0x3c, 0x79, 0xd4, 0x6f, 0xc0, 0xc1, 0xaf, 0x60, 0xc2, 0x91, 0x70, 0xf2, 0x64, 0x0c, 0x1c, 0xf0, + 0x63, 0x98, 0xee, 0x4c, 0x97, 0x1d, 0xe8, 0x96, 0x56, 0xbd, 0xc0, 0xec, 0x7b, 0xbf, 0xf7, 0xde, + 0xef, 0xfd, 0x99, 0x37, 0x85, 0xb7, 0x3b, 0x9e, 0xeb, 0xe2, 0x0e, 0xd5, 0x1c, 0x23, 0xd8, 0xc6, + 0xd4, 0x31, 0x7c, 0x2d, 0xac, 0x69, 0x74, 0x57, 0xf5, 0x03, 0x8f, 0x7a, 0xa8, 0xc4, 0xd5, 0x6a, + 0xac, 0x56, 0xc3, 0x9a, 0x3c, 0xd7, 0xf1, 0x88, 0xe3, 0x11, 0xcd, 0x21, 0x96, 0x16, 0xde, 0xeb, + 0xfd, 0x63, 0x70, 0xb9, 0x64, 0x79, 0x96, 0x17, 0x1d, 0xb5, 0xde, 0x89, 0x4b, 0x6f, 0x32, 0x78, + 0x9b, 0x29, 0xd8, 0x07, 0x57, 0xcd, 0x1a, 0x8e, 0xed, 0x7a, 0x5a, 0xf4, 0x97, 0x8b, 0xee, 0x0c, + 0x64, 0xc4, 0x3e, 0x86, 0x42, 0x7c, 0x23, 0x30, 0x1c, 0xee, 0x58, 0xf9, 0x0e, 0xe0, 0x4c, 0x8b, + 0x58, 0x1b, 0x3e, 0xc1, 0x01, 0x6d, 0x45, 0x30, 0x82, 0x1e, 0xc0, 0xbc, 0xd1, 0xa5, 0x5b, 0x5e, + 0x60, 0xd3, 0x3d, 0x09, 0xcc, 0x83, 0xa5, 0x7c, 0x53, 0x3a, 0xfa, 0xb6, 0x52, 0xe2, 0x94, 0x1a, + 0xa6, 0x19, 0x60, 0x42, 0x5e, 0xd0, 0xc0, 0x76, 0x2d, 0xfd, 0x0c, 0x8a, 0x1e, 0xc1, 0x2b, 0x2c, + 0x12, 0x91, 0xb2, 0xf3, 0x13, 0x4b, 0xd7, 0x6a, 0xb7, 0xd4, 0x41, 0x75, 0x51, 0x59, 0x9c, 0xe6, + 0xe4, 0xc1, 0xcf, 0x4a, 0x46, 0xef, 0x9b, 0xd4, 0x1f, 0xfe, 0xfe, 0x52, 0xc9, 0xbc, 0x39, 0xdd, + 0x5f, 0x3e, 0xf3, 0xf8, 0xfe, 0x74, 0x7f, 0x79, 0xa1, 0x9f, 0xc4, 0x6e, 0x22, 0x8d, 0xf3, 0x94, + 0x95, 0x43, 0x00, 0xa5, 0xf3, 0x42, 0x1d, 0x13, 0xdf, 0x73, 0x09, 0x46, 0x3b, 0xb0, 0xc8, 0x4c, + 0xdb, 0x5d, 0xdf, 0x34, 0x28, 0x26, 0x12, 0x88, 0xe8, 0x35, 0x52, 0xe8, 0xa5, 0xf8, 0xe1, 0xbc, + 0x37, 0x98, 0x8f, 0x27, 0x2e, 0x0d, 0xf6, 0x9a, 0x59, 0x09, 0xe8, 0x05, 0x27, 0x29, 0x97, 0x1f, + 0x43, 0x74, 0x11, 0x88, 0x66, 0xe0, 0xc4, 0x36, 0xe6, 0xd5, 0xd4, 0x7b, 0x47, 0x54, 0x82, 0xb9, + 0xd0, 0xd8, 0xe9, 0x62, 0x29, 0x3b, 0x0f, 0x96, 0xae, 0xea, 0xec, 0xa3, 0x9e, 0x5d, 0x03, 0xf5, + 0xc9, 0xcf, 0x5f, 0x2b, 0x40, 0x39, 0x62, 0xad, 0x59, 0x0f, 0xb0, 0x41, 0xf1, 0xbf, 0xb6, 0xe6, + 0x29, 0x2c, 0x76, 0x22, 0x47, 0xed, 0xf1, 0x3b, 0x54, 0xe8, 0x24, 0x29, 0x8c, 0xdb, 0x27, 0x81, + 0xbf, 0x22, 0x47, 0x6d, 0x12, 0x64, 0xfd, 0xf2, 0xf6, 0x13, 0x66, 0x65, 0xfb, 0x0f, 0x09, 0xb3, + 0x66, 0xff, 0x4d, 0xc2, 0xdd, 0x24, 0x85, 0xf1, 0x07, 0xd3, 0xbc, 0x90, 0xb0, 0x20, 0x8b, 0x13, + 0xfe, 0x00, 0x60, 0xbe, 0x45, 0xac, 0xe7, 0xd1, 0x85, 0x44, 0x75, 0x38, 0xc5, 0xae, 0x66, 0x94, + 0x66, 0x2a, 0x53, 0x86, 0xe6, 0x4c, 0xb9, 0x85, 0x58, 0xa5, 0xec, 0xc8, 0x55, 0xaa, 0x17, 0xc5, + 0xb4, 0x94, 0x1b, 0x70, 0x36, 0x26, 0x14, 0xd3, 0x7c, 0x0b, 0xa0, 0xdc, 0x22, 0x96, 0x8e, 0x1d, + 0x2f, 0xe4, 0x39, 0x34, 0xb8, 0x85, 0x8d, 0x09, 0xba, 0x0b, 0x67, 0x82, 0x48, 0xd5, 0x36, 0x58, + 0x18, 0x7e, 0xbf, 0xf2, 0xfa, 0x34, 0x93, 0x37, 0xfa, 0x62, 0xa4, 0xc2, 0x9c, 0x61, 0x3a, 0xb6, + 0x7b, 0x29, 0x45, 0x06, 0xab, 0xc3, 0x1e, 0x3d, 0x76, 0x56, 0x16, 0xa0, 0x92, 0x4e, 0x22, 0xe6, + 0xba, 0x15, 0x8d, 0x50, 0x12, 0x95, 0x88, 0x0a, 0x46, 0x8a, 0x8a, 0x24, 0x71, 0x8d, 0xe5, 0xcf, + 0x56, 0x54, 0x92, 0xcf, 0x7a, 0xd4, 0x58, 0x21, 0x52, 0xbc, 0x70, 0x16, 0xe1, 0xb4, 0x89, 0x77, + 0x30, 0xc5, 0x66, 0x3c, 0x7d, 0xac, 0x22, 0x45, 0x2e, 0xe6, 0x06, 0xb5, 0x4f, 0x39, 0x38, 0xd1, + 0x22, 0x16, 0xb2, 0x60, 0x41, 0xbc, 0xe7, 0xd5, 0xd4, 0xd5, 0x24, 0xe0, 0x64, 0x75, 0x34, 0x5c, + 0xcc, 0xcc, 0x82, 0x05, 0xf1, 0x7e, 0x55, 0x87, 0xec, 0x40, 0x73, 0xa4, 0x40, 0x03, 0x67, 0x1b, + 0xbd, 0x84, 0xd7, 0x99, 0x82, 0x4f, 0x77, 0x25, 0xd5, 0x9e, 0x01, 0xe4, 0xc5, 0x4b, 0x00, 0xb1, + 0xe7, 0x77, 0x00, 0xce, 0xa5, 0xcd, 0xe2, 0x6a, 0xaa, 0x93, 0x14, 0x0b, 0x79, 0x6d, 0x5c, 0x0b, + 0xb1, 0x94, 0xc9, 0x67, 0xb3, 0x3a, 0xda, 0x73, 0x32, 0xb4, 0x94, 0x83, 0x9e, 0x2f, 0x0b, 0x16, + 0xc4, 0x81, 0xae, 0x8e, 0xc4, 0x79, 0x58, 0xa0, 0x81, 0x63, 0x2b, 0xe7, 0x5e, 0x9f, 0xee, 0x2f, + 0x83, 0xe6, 0xb3, 0x83, 0xe3, 0x32, 0x38, 0x3c, 0x2e, 0x83, 0x5f, 0xc7, 0x65, 0xf0, 0xf1, 0xa4, + 0x9c, 0x39, 0x3c, 0x29, 0x67, 0x7e, 0x9c, 0x94, 0x33, 0xaf, 0x56, 0x2d, 0x9b, 0x6e, 0x75, 0x37, + 0xd5, 0x8e, 0xe7, 0x68, 0x64, 0xdb, 0xf6, 0x57, 0x1c, 0x1c, 0x6a, 0xfd, 0x35, 0x18, 0xd6, 0x84, + 0x4d, 0x48, 0xf7, 0x7c, 0x4c, 0x36, 0xa7, 0xa2, 0x9f, 0x19, 0xf7, 0xff, 0x04, 0x00, 0x00, 0xff, + 0xff, 0x17, 0x6d, 0xc6, 0xd8, 0x40, 0x09, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -606,6 +715,10 @@ type MsgClient interface { // Specifically if a market does not exist it will be created, otherwise it // will be updated. The response will be a map between ticker -> updated. UpsertMarkets(ctx context.Context, in *MsgUpsertMarkets, opts ...grpc.CallOption) (*MsgUpsertMarketsResponse, error) + // RemoveMarkets removes the given markets from the marketmap if: + // - they exist in the map + // - they are disabled + RemoveMarkets(ctx context.Context, in *MsgRemoveMarkets, opts ...grpc.CallOption) (*MsgRemoveMarketsResponse, error) } type msgClient struct { @@ -661,6 +774,15 @@ func (c *msgClient) UpsertMarkets(ctx context.Context, in *MsgUpsertMarkets, opt return out, nil } +func (c *msgClient) RemoveMarkets(ctx context.Context, in *MsgRemoveMarkets, opts ...grpc.CallOption) (*MsgRemoveMarketsResponse, error) { + out := new(MsgRemoveMarketsResponse) + err := c.cc.Invoke(ctx, "/connect.marketmap.v2.Msg/RemoveMarkets", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // MsgServer is the server API for Msg service. type MsgServer interface { // CreateMarkets creates markets from the given message. @@ -677,6 +799,10 @@ type MsgServer interface { // Specifically if a market does not exist it will be created, otherwise it // will be updated. The response will be a map between ticker -> updated. UpsertMarkets(context.Context, *MsgUpsertMarkets) (*MsgUpsertMarketsResponse, error) + // RemoveMarkets removes the given markets from the marketmap if: + // - they exist in the map + // - they are disabled + RemoveMarkets(context.Context, *MsgRemoveMarkets) (*MsgRemoveMarketsResponse, error) } // UnimplementedMsgServer can be embedded to have forward compatible implementations. @@ -698,6 +824,9 @@ func (*UnimplementedMsgServer) RemoveMarketAuthorities(ctx context.Context, req func (*UnimplementedMsgServer) UpsertMarkets(ctx context.Context, req *MsgUpsertMarkets) (*MsgUpsertMarketsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method UpsertMarkets not implemented") } +func (*UnimplementedMsgServer) RemoveMarkets(ctx context.Context, req *MsgRemoveMarkets) (*MsgRemoveMarketsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RemoveMarkets not implemented") +} func RegisterMsgServer(s grpc1.Server, srv MsgServer) { s.RegisterService(&_Msg_serviceDesc, srv) @@ -793,6 +922,24 @@ func _Msg_UpsertMarkets_Handler(srv interface{}, ctx context.Context, dec func(i return interceptor(ctx, in, info, handler) } +func _Msg_RemoveMarkets_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgRemoveMarkets) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).RemoveMarkets(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/connect.marketmap.v2.Msg/RemoveMarkets", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).RemoveMarkets(ctx, req.(*MsgRemoveMarkets)) + } + return interceptor(ctx, in, info, handler) +} + var Msg_serviceDesc = _Msg_serviceDesc var _Msg_serviceDesc = grpc.ServiceDesc{ ServiceName: "connect.marketmap.v2.Msg", @@ -818,6 +965,10 @@ var _Msg_serviceDesc = grpc.ServiceDesc{ MethodName: "UpsertMarkets", Handler: _Msg_UpsertMarkets_Handler, }, + { + MethodName: "RemoveMarkets", + Handler: _Msg_RemoveMarkets_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "connect/marketmap/v2/tx.proto", @@ -1176,6 +1327,77 @@ func (m *MsgRemoveMarketAuthoritiesResponse) MarshalToSizedBuffer(dAtA []byte) ( return len(dAtA) - i, nil } +func (m *MsgRemoveMarkets) 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 *MsgRemoveMarkets) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgRemoveMarkets) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Markets) > 0 { + for iNdEx := len(m.Markets) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Markets[iNdEx]) + copy(dAtA[i:], m.Markets[iNdEx]) + i = encodeVarintTx(dAtA, i, uint64(len(m.Markets[iNdEx]))) + i-- + dAtA[i] = 0x12 + } + } + if len(m.Admin) > 0 { + i -= len(m.Admin) + copy(dAtA[i:], m.Admin) + i = encodeVarintTx(dAtA, i, uint64(len(m.Admin))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgRemoveMarketsResponse) 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 *MsgRemoveMarketsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgRemoveMarketsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.DeletedMarkets) > 0 { + for iNdEx := len(m.DeletedMarkets) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.DeletedMarkets[iNdEx]) + copy(dAtA[i:], m.DeletedMarkets[iNdEx]) + i = encodeVarintTx(dAtA, i, uint64(len(m.DeletedMarkets[iNdEx]))) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + func encodeVarintTx(dAtA []byte, offset int, v uint64) int { offset -= sovTx(v) base := offset @@ -1331,6 +1553,40 @@ func (m *MsgRemoveMarketAuthoritiesResponse) Size() (n int) { return n } +func (m *MsgRemoveMarkets) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Admin) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if len(m.Markets) > 0 { + for _, s := range m.Markets { + l = len(s) + n += 1 + l + sovTx(uint64(l)) + } + } + return n +} + +func (m *MsgRemoveMarketsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.DeletedMarkets) > 0 { + for _, s := range m.DeletedMarkets { + l = len(s) + n += 1 + l + sovTx(uint64(l)) + } + } + return n +} + func sovTx(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -2279,6 +2535,202 @@ func (m *MsgRemoveMarketAuthoritiesResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *MsgRemoveMarkets) 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: MsgRemoveMarkets: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgRemoveMarkets: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Admin", 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.Admin = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Markets", 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.Markets = append(m.Markets, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgRemoveMarketsResponse) 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: MsgRemoveMarketsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgRemoveMarketsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DeletedMarkets", 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.DeletedMarkets = append(m.DeletedMarkets, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipTx(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/marketmap/types/validation_hooks.go b/x/marketmap/types/validation_hooks.go new file mode 100644 index 000000000..d812aee85 --- /dev/null +++ b/x/marketmap/types/validation_hooks.go @@ -0,0 +1,47 @@ +package types + +import ( + "context" + "fmt" +) + +// MarketValidationHook is a hook that is called for stateful validation of a market before +// some keeper operation is performed on it. +type MarketValidationHook func(ctx context.Context, market Market) error + +// MarketValidationHooks is a type alias for an array of MarketValidationHook. +type MarketValidationHooks []MarketValidationHook + +// ValidateMarket calls all validation hooks for the given market. +func (h MarketValidationHooks) ValidateMarket(ctx context.Context, market Market) error { + for _, hook := range h { + if err := hook(ctx, market); err != nil { + return fmt.Errorf("failed validation hooks for market %s: %w", market.Ticker.String(), err) + } + } + + return nil +} + +// DefaultDeleteMarketValidationHooks returns the default DeleteMarketValidationHook as an array. +func DefaultDeleteMarketValidationHooks() MarketValidationHooks { + hooks := MarketValidationHooks{ + DefaultDeleteMarketValidationHook(), + } + + return hooks +} + +// DefaultDeleteMarketValidationHook returns the default DeleteMarketValidationHook for x/marketmap. +// This hook checks: +// - if the given market is enabled - error +// - if the given market is disabled - return nil. +func DefaultDeleteMarketValidationHook() MarketValidationHook { + return func(_ context.Context, market Market) error { + if market.Ticker.Enabled { + return fmt.Errorf("market is enabled - cannot be deleted") + } + + return nil + } +} diff --git a/x/marketmap/types/validation_hooks_test.go b/x/marketmap/types/validation_hooks_test.go new file mode 100644 index 000000000..877a16852 --- /dev/null +++ b/x/marketmap/types/validation_hooks_test.go @@ -0,0 +1,64 @@ +package types_test + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + + connecttypes "github.com/skip-mev/connect/v2/pkg/types" + "github.com/skip-mev/connect/v2/x/marketmap/types" +) + +func TestDefaultDeleteMarketValidationHooks_ValidateMarket(t *testing.T) { + tests := []struct { + name string + market types.Market + wantErr bool + }{ + { + name: "valid - disabled market", + market: types.Market{ + Ticker: types.Ticker{ + CurrencyPair: connecttypes.CurrencyPair{ + Base: "BTC", + Quote: "USD", + }, + Decimals: 3, + MinProviderCount: 3, + Enabled: false, + Metadata_JSON: "", + }, + }, + wantErr: false, + }, + { + name: "invalid - enabled market", + market: types.Market{ + Ticker: types.Ticker{ + CurrencyPair: connecttypes.CurrencyPair{ + Base: "BTC", + Quote: "USD", + }, + Decimals: 3, + MinProviderCount: 3, + Enabled: true, + Metadata_JSON: "", + }, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + hooks := types.DefaultDeleteMarketValidationHooks() + + err := hooks.ValidateMarket(context.Background(), tt.market) + if tt.wantErr { + require.Error(t, err) + return + } + require.NoError(t, err) + }) + } +} diff --git a/x/oracle/keeper/hooks.go b/x/oracle/keeper/hooks.go index 64abcee26..d228b425a 100644 --- a/x/oracle/keeper/hooks.go +++ b/x/oracle/keeper/hooks.go @@ -24,13 +24,14 @@ func (k *Keeper) Hooks() Hooks { // the marketmap. After the market is created, a currency pair and its state are initialized in the // oracle module. func (h Hooks) AfterMarketCreated(ctx sdk.Context, market marketmaptypes.Market) error { + ctx.Logger().Info(fmt.Sprintf("creating x/oracle state for market %s", market.Ticker.String())) return h.k.CreateCurrencyPair(ctx, market.Ticker.CurrencyPair) } // AfterMarketUpdated is the marketmap hook for x/oracle that is run after a market is updated in // the marketmap. -func (h Hooks) AfterMarketUpdated(_ sdk.Context, _ marketmaptypes.Market) error { - // TODO +func (h Hooks) AfterMarketUpdated(ctx sdk.Context, market marketmaptypes.Market) error { + ctx.Logger().Info(fmt.Sprintf("market %s updated", market.Ticker.String())) return nil } @@ -45,3 +46,10 @@ func (h Hooks) AfterMarketGenesis(ctx sdk.Context, markets map[string]marketmapt return nil } + +// AfterMarketRemoved is the marketmap hook for x/oracle that is run after a market is removed in +// the marketmap. +func (h Hooks) AfterMarketRemoved(ctx sdk.Context, market marketmaptypes.Market) error { + ctx.Logger().Info(fmt.Sprintf("market %s removed. retaining x/oracle state if it exists", market.Ticker.String())) + return nil +}