diff --git a/go.mod b/go.mod index 5aebb30f89..eb08adac02 100644 --- a/go.mod +++ b/go.mod @@ -41,7 +41,7 @@ require ( github.com/smartcontractkit/chain-selectors v1.0.89 github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.10 github.com/smartcontractkit/chainlink-protos/billing/go v0.0.0-20251024234028-0988426d98f4 - github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260204211151-e87a8bf189b0 + github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260206000552-087e235a7963 github.com/smartcontractkit/chainlink-protos/linking-service/go v0.0.0-20251002192024-d2ad9222409b github.com/smartcontractkit/chainlink-protos/storage-service v0.3.0 github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260106052706-6dd937cb5ec6 diff --git a/go.sum b/go.sum index 2a9fbbde17..ae984dbbff 100644 --- a/go.sum +++ b/go.sum @@ -332,8 +332,8 @@ github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.10 h1:FJAFgXS9 github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.10/go.mod h1:oiDa54M0FwxevWwyAX773lwdWvFYYlYHHQV1LQ5HpWY= github.com/smartcontractkit/chainlink-protos/billing/go v0.0.0-20251024234028-0988426d98f4 h1:GCzrxDWn3b7jFfEA+WiYRi8CKoegsayiDoJBCjYkneE= github.com/smartcontractkit/chainlink-protos/billing/go v0.0.0-20251024234028-0988426d98f4/go.mod h1:HHGeDUpAsPa0pmOx7wrByCitjQ0mbUxf0R9v+g67uCA= -github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260204211151-e87a8bf189b0 h1:+/0xWigvOxFLghyivyxiUCYGcky/7i8IxfGTdTeaXFg= -github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260204211151-e87a8bf189b0/go.mod h1:Jqt53s27Tr0jDl8mdBXg1xhu6F8Fci8JOuq43tgHOM8= +github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260206000552-087e235a7963 h1:DCLvEn4KkFzYbK/AYl4vJmf6EHaskPYvGDGdd0kOma0= +github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260206000552-087e235a7963/go.mod h1:Jqt53s27Tr0jDl8mdBXg1xhu6F8Fci8JOuq43tgHOM8= github.com/smartcontractkit/chainlink-protos/linking-service/go v0.0.0-20251002192024-d2ad9222409b h1:QuI6SmQFK/zyUlVWEf0GMkiUYBPY4lssn26nKSd/bOM= github.com/smartcontractkit/chainlink-protos/linking-service/go v0.0.0-20251002192024-d2ad9222409b/go.mod h1:qSTSwX3cBP3FKQwQacdjArqv0g6QnukjV4XuzO6UyoY= github.com/smartcontractkit/chainlink-protos/storage-service v0.3.0 h1:B7itmjy+CMJ26elVw/cAJqqhBQ3Xa/mBYWK0/rQ5MuI= diff --git a/pkg/capabilities/v2/actions/confidentialhttp/client.pb.go b/pkg/capabilities/v2/actions/confidentialhttp/client.pb.go index 76d76e89dc..c760b38391 100644 --- a/pkg/capabilities/v2/actions/confidentialhttp/client.pb.go +++ b/pkg/capabilities/v2/actions/confidentialhttp/client.pb.go @@ -83,30 +83,28 @@ func (x *SecretIdentifier) GetOwner() string { return "" } -// Header represents a single HTTP header as a name-value pair. -// Using repeated messages instead of a map allows duplicate header names (e.g., multiple Set-Cookie headers). -type Header struct { +// HeaderValues represents multiple values for a single header key. +type HeaderValues struct { state protoimpl.MessageState `protogen:"open.v1"` - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` + Values []string `protobuf:"bytes,1,rep,name=values,proto3" json:"values,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } -func (x *Header) Reset() { - *x = Header{} +func (x *HeaderValues) Reset() { + *x = HeaderValues{} mi := &file_capabilities_networking_confidentialhttp_v1alpha_client_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } -func (x *Header) String() string { +func (x *HeaderValues) String() string { return protoimpl.X.MessageStringOf(x) } -func (*Header) ProtoMessage() {} +func (*HeaderValues) ProtoMessage() {} -func (x *Header) ProtoReflect() protoreflect.Message { +func (x *HeaderValues) ProtoReflect() protoreflect.Message { mi := &file_capabilities_networking_confidentialhttp_v1alpha_client_proto_msgTypes[1] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -118,23 +116,16 @@ func (x *Header) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use Header.ProtoReflect.Descriptor instead. -func (*Header) Descriptor() ([]byte, []int) { +// Deprecated: Use HeaderValues.ProtoReflect.Descriptor instead. +func (*HeaderValues) Descriptor() ([]byte, []int) { return file_capabilities_networking_confidentialhttp_v1alpha_client_proto_rawDescGZIP(), []int{1} } -func (x *Header) GetName() string { +func (x *HeaderValues) GetValues() []string { if x != nil { - return x.Name + return x.Values } - return "" -} - -func (x *Header) GetValue() string { - if x != nil { - return x.Value - } - return "" + return nil } // HTTPRequest contains the HTTP fields used to make a request from the enclave. @@ -151,8 +142,9 @@ type HTTPRequest struct { // *HTTPRequest_BodyString // *HTTPRequest_BodyBytes Body isHTTPRequest_Body `protobuf_oneof:"body"` - // headers are the request headers as name-value pairs. - Headers map[string]string `protobuf:"bytes,4,rep,name=headers,proto3" json:"headers,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + // multi_headers are the request headers as name-value pairs. + // Supports multiple values per header key. + MultiHeaders map[string]*HeaderValues `protobuf:"bytes,4,rep,name=multi_headers,json=multiHeaders,proto3" json:"multi_headers,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` // template_public_values are public values used to fill in request body and header templates. TemplatePublicValues map[string]string `protobuf:"bytes,5,rep,name=template_public_values,json=templatePublicValues,proto3" json:"template_public_values,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` // custom_root_ca_cert_pem is an optional custom root CA certificate (PEM format) @@ -233,9 +225,9 @@ func (x *HTTPRequest) GetBodyBytes() []byte { return nil } -func (x *HTTPRequest) GetHeaders() map[string]string { +func (x *HTTPRequest) GetMultiHeaders() map[string]*HeaderValues { if x != nil { - return x.Headers + return x.MultiHeaders } return nil } @@ -284,8 +276,9 @@ type HTTPResponse struct { StatusCode uint32 `protobuf:"varint,1,opt,name=status_code,json=statusCode,proto3" json:"status_code,omitempty"` // body is the response body. Body []byte `protobuf:"bytes,2,opt,name=body,proto3" json:"body,omitempty"` - // headers are the response headers. - Headers []*Header `protobuf:"bytes,3,rep,name=headers,proto3" json:"headers,omitempty"` + // multi_headers are the response headers. + // Supports multiple values per header key. + MultiHeaders map[string]*HeaderValues `protobuf:"bytes,3,rep,name=multi_headers,json=multiHeaders,proto3" json:"multi_headers,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -334,9 +327,9 @@ func (x *HTTPResponse) GetBody() []byte { return nil } -func (x *HTTPResponse) GetHeaders() []*Header { +func (x *HTTPResponse) GetMultiHeaders() map[string]*HeaderValues { if x != nil { - return x.Headers + return x.MultiHeaders } return nil } @@ -347,8 +340,15 @@ type ConfidentialHTTPRequest struct { state protoimpl.MessageState `protogen:"open.v1"` VaultDonSecrets []*SecretIdentifier `protobuf:"bytes,1,rep,name=vault_don_secrets,json=vaultDonSecrets,proto3" json:"vault_don_secrets,omitempty"` Request *HTTPRequest `protobuf:"bytes,2,opt,name=request,proto3" json:"request,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + // encrypt_output controls whether the enclave response should be encrypted. + // If true and a secret named "san_marino_aes_gcm_encryption_key" is provided, + // the response will be AES-GCM encrypted using that key. + // If true and no such key is provided, the response will be TDH2 encrypted + // using the VaultDON master public key. + // Default is false (response returned unencrypted). + EncryptOutput bool `protobuf:"varint,3,opt,name=encrypt_output,json=encryptOutput,proto3" json:"encrypt_output,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *ConfidentialHTTPRequest) Reset() { @@ -395,6 +395,13 @@ func (x *ConfidentialHTTPRequest) GetRequest() *HTTPRequest { return nil } +func (x *ConfidentialHTTPRequest) GetEncryptOutput() bool { + if x != nil { + return x.EncryptOutput + } + return false +} + var File_capabilities_networking_confidentialhttp_v1alpha_client_proto protoreflect.FileDescriptor const file_capabilities_networking_confidentialhttp_v1alpha_client_proto_rawDesc = "" + @@ -404,36 +411,39 @@ const file_capabilities_networking_confidentialhttp_v1alpha_client_proto_rawDesc "\x03key\x18\x01 \x01(\tR\x03key\x12\x1c\n" + "\tnamespace\x18\x02 \x01(\tR\tnamespace\x12\x19\n" + "\x05owner\x18\x03 \x01(\tH\x00R\x05owner\x88\x01\x01B\b\n" + - "\x06_owner\"2\n" + - "\x06Header\x12\x12\n" + - "\x04name\x18\x01 \x01(\tR\x04name\x12\x14\n" + - "\x05value\x18\x02 \x01(\tR\x05value\"\xe9\x04\n" + + "\x06_owner\"&\n" + + "\fHeaderValues\x12\x16\n" + + "\x06values\x18\x01 \x03(\tR\x06values\"\xbe\x05\n" + "\vHTTPRequest\x12\x10\n" + "\x03url\x18\x01 \x01(\tR\x03url\x12\x16\n" + "\x06method\x18\x02 \x01(\tR\x06method\x12!\n" + "\vbody_string\x18\x03 \x01(\tH\x00R\n" + "bodyString\x12\x1f\n" + "\n" + - "body_bytes\x18\b \x01(\fH\x00R\tbodyBytes\x12d\n" + - "\aheaders\x18\x04 \x03(\v2J.capabilities.networking.confidentialhttp.v1alpha.HTTPRequest.HeadersEntryR\aheaders\x12\x8d\x01\n" + + "body_bytes\x18\b \x01(\fH\x00R\tbodyBytes\x12t\n" + + "\rmulti_headers\x18\x04 \x03(\v2O.capabilities.networking.confidentialhttp.v1alpha.HTTPRequest.MultiHeadersEntryR\fmultiHeaders\x12\x8d\x01\n" + "\x16template_public_values\x18\x05 \x03(\v2W.capabilities.networking.confidentialhttp.v1alpha.HTTPRequest.TemplatePublicValuesEntryR\x14templatePublicValues\x124\n" + "\x17custom_root_ca_cert_pem\x18\x06 \x01(\fR\x13customRootCaCertPem\x123\n" + - "\atimeout\x18\a \x01(\v2\x19.google.protobuf.DurationR\atimeout\x1a:\n" + - "\fHeadersEntry\x12\x10\n" + - "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + - "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\x1aG\n" + + "\atimeout\x18\a \x01(\v2\x19.google.protobuf.DurationR\atimeout\x1a\x7f\n" + + "\x11MultiHeadersEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12T\n" + + "\x05value\x18\x02 \x01(\v2>.capabilities.networking.confidentialhttp.v1alpha.HeaderValuesR\x05value:\x028\x01\x1aG\n" + "\x19TemplatePublicValuesEntry\x12\x10\n" + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01B\x06\n" + - "\x04body\"\x97\x01\n" + + "\x04body\"\xbb\x02\n" + "\fHTTPResponse\x12\x1f\n" + "\vstatus_code\x18\x01 \x01(\rR\n" + "statusCode\x12\x12\n" + - "\x04body\x18\x02 \x01(\fR\x04body\x12R\n" + - "\aheaders\x18\x03 \x03(\v28.capabilities.networking.confidentialhttp.v1alpha.HeaderR\aheaders\"\xe2\x01\n" + + "\x04body\x18\x02 \x01(\fR\x04body\x12u\n" + + "\rmulti_headers\x18\x03 \x03(\v2P.capabilities.networking.confidentialhttp.v1alpha.HTTPResponse.MultiHeadersEntryR\fmultiHeaders\x1a\x7f\n" + + "\x11MultiHeadersEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12T\n" + + "\x05value\x18\x02 \x01(\v2>.capabilities.networking.confidentialhttp.v1alpha.HeaderValuesR\x05value:\x028\x01\"\x89\x02\n" + "\x17ConfidentialHTTPRequest\x12n\n" + "\x11vault_don_secrets\x18\x01 \x03(\v2B.capabilities.networking.confidentialhttp.v1alpha.SecretIdentifierR\x0fvaultDonSecrets\x12W\n" + - "\arequest\x18\x02 \x01(\v2=.capabilities.networking.confidentialhttp.v1alpha.HTTPRequestR\arequest2\xca\x01\n" + + "\arequest\x18\x02 \x01(\v2=.capabilities.networking.confidentialhttp.v1alpha.HTTPRequestR\arequest\x12%\n" + + "\x0eencrypt_output\x18\x03 \x01(\bR\rencryptOutput2\xca\x01\n" + "\x06Client\x12\x98\x01\n" + "\vSendRequest\x12I.capabilities.networking.confidentialhttp.v1alpha.ConfidentialHTTPRequest\x1a>.capabilities.networking.confidentialhttp.v1alpha.HTTPResponse\x1a%\x82\xb5\x18!\b\x02\x12\x1dconfidential-http@1.0.0-alphab\x06proto3" @@ -449,31 +459,34 @@ func file_capabilities_networking_confidentialhttp_v1alpha_client_proto_rawDescG return file_capabilities_networking_confidentialhttp_v1alpha_client_proto_rawDescData } -var file_capabilities_networking_confidentialhttp_v1alpha_client_proto_msgTypes = make([]protoimpl.MessageInfo, 7) +var file_capabilities_networking_confidentialhttp_v1alpha_client_proto_msgTypes = make([]protoimpl.MessageInfo, 8) var file_capabilities_networking_confidentialhttp_v1alpha_client_proto_goTypes = []any{ (*SecretIdentifier)(nil), // 0: capabilities.networking.confidentialhttp.v1alpha.SecretIdentifier - (*Header)(nil), // 1: capabilities.networking.confidentialhttp.v1alpha.Header + (*HeaderValues)(nil), // 1: capabilities.networking.confidentialhttp.v1alpha.HeaderValues (*HTTPRequest)(nil), // 2: capabilities.networking.confidentialhttp.v1alpha.HTTPRequest (*HTTPResponse)(nil), // 3: capabilities.networking.confidentialhttp.v1alpha.HTTPResponse (*ConfidentialHTTPRequest)(nil), // 4: capabilities.networking.confidentialhttp.v1alpha.ConfidentialHTTPRequest - nil, // 5: capabilities.networking.confidentialhttp.v1alpha.HTTPRequest.HeadersEntry + nil, // 5: capabilities.networking.confidentialhttp.v1alpha.HTTPRequest.MultiHeadersEntry nil, // 6: capabilities.networking.confidentialhttp.v1alpha.HTTPRequest.TemplatePublicValuesEntry - (*durationpb.Duration)(nil), // 7: google.protobuf.Duration + nil, // 7: capabilities.networking.confidentialhttp.v1alpha.HTTPResponse.MultiHeadersEntry + (*durationpb.Duration)(nil), // 8: google.protobuf.Duration } var file_capabilities_networking_confidentialhttp_v1alpha_client_proto_depIdxs = []int32{ - 5, // 0: capabilities.networking.confidentialhttp.v1alpha.HTTPRequest.headers:type_name -> capabilities.networking.confidentialhttp.v1alpha.HTTPRequest.HeadersEntry + 5, // 0: capabilities.networking.confidentialhttp.v1alpha.HTTPRequest.multi_headers:type_name -> capabilities.networking.confidentialhttp.v1alpha.HTTPRequest.MultiHeadersEntry 6, // 1: capabilities.networking.confidentialhttp.v1alpha.HTTPRequest.template_public_values:type_name -> capabilities.networking.confidentialhttp.v1alpha.HTTPRequest.TemplatePublicValuesEntry - 7, // 2: capabilities.networking.confidentialhttp.v1alpha.HTTPRequest.timeout:type_name -> google.protobuf.Duration - 1, // 3: capabilities.networking.confidentialhttp.v1alpha.HTTPResponse.headers:type_name -> capabilities.networking.confidentialhttp.v1alpha.Header + 8, // 2: capabilities.networking.confidentialhttp.v1alpha.HTTPRequest.timeout:type_name -> google.protobuf.Duration + 7, // 3: capabilities.networking.confidentialhttp.v1alpha.HTTPResponse.multi_headers:type_name -> capabilities.networking.confidentialhttp.v1alpha.HTTPResponse.MultiHeadersEntry 0, // 4: capabilities.networking.confidentialhttp.v1alpha.ConfidentialHTTPRequest.vault_don_secrets:type_name -> capabilities.networking.confidentialhttp.v1alpha.SecretIdentifier 2, // 5: capabilities.networking.confidentialhttp.v1alpha.ConfidentialHTTPRequest.request:type_name -> capabilities.networking.confidentialhttp.v1alpha.HTTPRequest - 4, // 6: capabilities.networking.confidentialhttp.v1alpha.Client.SendRequest:input_type -> capabilities.networking.confidentialhttp.v1alpha.ConfidentialHTTPRequest - 3, // 7: capabilities.networking.confidentialhttp.v1alpha.Client.SendRequest:output_type -> capabilities.networking.confidentialhttp.v1alpha.HTTPResponse - 7, // [7:8] is the sub-list for method output_type - 6, // [6:7] is the sub-list for method input_type - 6, // [6:6] is the sub-list for extension type_name - 6, // [6:6] is the sub-list for extension extendee - 0, // [0:6] is the sub-list for field type_name + 1, // 6: capabilities.networking.confidentialhttp.v1alpha.HTTPRequest.MultiHeadersEntry.value:type_name -> capabilities.networking.confidentialhttp.v1alpha.HeaderValues + 1, // 7: capabilities.networking.confidentialhttp.v1alpha.HTTPResponse.MultiHeadersEntry.value:type_name -> capabilities.networking.confidentialhttp.v1alpha.HeaderValues + 4, // 8: capabilities.networking.confidentialhttp.v1alpha.Client.SendRequest:input_type -> capabilities.networking.confidentialhttp.v1alpha.ConfidentialHTTPRequest + 3, // 9: capabilities.networking.confidentialhttp.v1alpha.Client.SendRequest:output_type -> capabilities.networking.confidentialhttp.v1alpha.HTTPResponse + 9, // [9:10] is the sub-list for method output_type + 8, // [8:9] is the sub-list for method input_type + 8, // [8:8] is the sub-list for extension type_name + 8, // [8:8] is the sub-list for extension extendee + 0, // [0:8] is the sub-list for field type_name } func init() { file_capabilities_networking_confidentialhttp_v1alpha_client_proto_init() } @@ -492,7 +505,7 @@ func file_capabilities_networking_confidentialhttp_v1alpha_client_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_capabilities_networking_confidentialhttp_v1alpha_client_proto_rawDesc), len(file_capabilities_networking_confidentialhttp_v1alpha_client_proto_rawDesc)), NumEnums: 0, - NumMessages: 7, + NumMessages: 8, NumExtensions: 0, NumServices: 1, }, diff --git a/pkg/capabilities/v2/chain-capabilities/solana/proto_helpers.go b/pkg/capabilities/v2/chain-capabilities/solana/proto_helpers.go new file mode 100644 index 0000000000..767173b57b --- /dev/null +++ b/pkg/capabilities/v2/chain-capabilities/solana/proto_helpers.go @@ -0,0 +1,155 @@ +package solana + +import ( + "fmt" + + chainsolana "github.com/smartcontractkit/chainlink-common/pkg/chains/solana" + typesolana "github.com/smartcontractkit/chainlink-common/pkg/types/chains/solana" + "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" +) + +// ConvertComparisonOperatorFromProto converts a proto ComparisonOperator to primitives.ComparisonOperator +func ConvertComparisonOperatorFromProto(op ComparisonOperator) (primitives.ComparisonOperator, error) { + switch op { + case ComparisonOperator_COMPARISON_OPERATOR_EQ: + return primitives.Eq, nil + case ComparisonOperator_COMPARISON_OPERATOR_NEQ: + return primitives.Neq, nil + case ComparisonOperator_COMPARISON_OPERATOR_GT: + return primitives.Gt, nil + case ComparisonOperator_COMPARISON_OPERATOR_LT: + return primitives.Lt, nil + case ComparisonOperator_COMPARISON_OPERATOR_GTE: + return primitives.Gte, nil + case ComparisonOperator_COMPARISON_OPERATOR_LTE: + return primitives.Lte, nil + default: + return 0, fmt.Errorf("unknown comparison operator: %s", op) + } +} + +// ConvertComparisonOperatorToProto converts a primitives.ComparisonOperator to proto ComparisonOperator +func ConvertComparisonOperatorToProto(op primitives.ComparisonOperator) (ComparisonOperator, error) { + switch op { + case primitives.Eq: + return ComparisonOperator_COMPARISON_OPERATOR_EQ, nil + case primitives.Neq: + return ComparisonOperator_COMPARISON_OPERATOR_NEQ, nil + case primitives.Gt: + return ComparisonOperator_COMPARISON_OPERATOR_GT, nil + case primitives.Lt: + return ComparisonOperator_COMPARISON_OPERATOR_LT, nil + case primitives.Gte: + return ComparisonOperator_COMPARISON_OPERATOR_GTE, nil + case primitives.Lte: + return ComparisonOperator_COMPARISON_OPERATOR_LTE, nil + default: + return 0, fmt.Errorf("unknown comparison operator: %s", op) + } +} + +// ConvertValueComparatorsFromProto converts proto ValueComparator slice to primitives.ValueComparator slice +func ConvertValueComparatorsFromProto(comparers []*ValueComparator) ([]primitives.ValueComparator, error) { + if comparers == nil { + return nil, nil + } + result := make([]primitives.ValueComparator, len(comparers)) + for i, c := range comparers { + if c != nil { + operator, err := ConvertComparisonOperatorFromProto(c.Operator) + if err != nil { + return nil, fmt.Errorf("failed to convert comparison operator: %w", err) + } + result[i] = primitives.ValueComparator{ + Value: c.Value, // []byte is compatible with any + Operator: operator, + } + } + } + return result, nil +} + +// ConvertValueComparatorsToProto converts primitives.ValueComparator slice to proto ValueComparator slice +func ConvertValueComparatorsToProto(comparers []primitives.ValueComparator) ([]*ValueComparator, error) { + if comparers == nil { + return nil, nil + } + result := make([]*ValueComparator, len(comparers)) + for i, c := range comparers { + // Handle the Value field which could be any type, convert to []byte if possible + var valueBytes []byte + if b, ok := c.Value.([]byte); ok { + valueBytes = b + } + operator, err := ConvertComparisonOperatorToProto(c.Operator) + if err != nil { + return nil, fmt.Errorf("failed to convert comparison operator: %w", err) + } + result[i] = &ValueComparator{ + Value: valueBytes, + Operator: operator, + } + } + return result, nil +} + +// ConvertLogFromProto converts a proto Log to typesolana.Log +func ConvertLogFromProto(p *Log) (*typesolana.Log, error) { + if p == nil { + return nil, nil + } + + blockHash, err := chainsolana.ConvertHashFromProto(p.BlockHash) + if err != nil { + return nil, fmt.Errorf("failed to convert block hash: %w", err) + } + + address, err := chainsolana.ConvertPublicKeyFromProto(p.Address) + if err != nil { + return nil, fmt.Errorf("failed to convert address: %w", err) + } + + eventSig, err := chainsolana.ConvertEventSigFromProto(p.EventSig) + if err != nil { + return nil, fmt.Errorf("failed to convert event sig: %w", err) + } + + txHash, err := chainsolana.ConvertSignatureFromProto(p.TxHash) + if err != nil { + return nil, fmt.Errorf("failed to convert tx hash: %w", err) + } + + return &typesolana.Log{ + ChainID: p.ChainId, + LogIndex: p.LogIndex, + BlockHash: blockHash, + BlockNumber: p.BlockNumber, + BlockTimestamp: p.BlockTimestamp, + Address: address, + EventSig: eventSig, + TxHash: txHash, + Data: p.Data, + SequenceNum: p.SequenceNum, + Error: p.Error, + }, nil +} + +// ConvertLogToProto converts a typesolana.Log to proto Log +func ConvertLogToProto(l *typesolana.Log) *Log { + if l == nil { + return nil + } + return &Log{ + ChainId: l.ChainID, + LogIndex: l.LogIndex, + BlockHash: l.BlockHash[:], + BlockNumber: l.BlockNumber, + BlockTimestamp: l.BlockTimestamp, + Address: l.Address[:], + EventSig: l.EventSig[:], + TxHash: l.TxHash[:], + Data: l.Data, + SequenceNum: l.SequenceNum, + Error: l.Error, + } +} diff --git a/pkg/chains/solana/solana.pb.go b/pkg/chains/solana/solana.pb.go index c692ede3ef..654b3c91e1 100644 --- a/pkg/chains/solana/solana.pb.go +++ b/pkg/chains/solana/solana.pb.go @@ -3940,6 +3940,51 @@ func (x *GetLatestLPBlockReply) GetSlot() uint64 { return 0 } +// GetFiltersNames returns all registered filter names +type GetFiltersNamesReply struct { + state protoimpl.MessageState `protogen:"open.v1"` + Items []string `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetFiltersNamesReply) Reset() { + *x = GetFiltersNamesReply{} + mi := &file_solana_proto_msgTypes[61] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetFiltersNamesReply) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetFiltersNamesReply) ProtoMessage() {} + +func (x *GetFiltersNamesReply) ProtoReflect() protoreflect.Message { + mi := &file_solana_proto_msgTypes[61] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetFiltersNamesReply.ProtoReflect.Descriptor instead. +func (*GetFiltersNamesReply) Descriptor() ([]byte, []int) { + return file_solana_proto_rawDescGZIP(), []int{61} +} + +func (x *GetFiltersNamesReply) GetItems() []string { + if x != nil { + return x.Items + } + return nil +} + var File_solana_proto protoreflect.FileDescriptor const file_solana_proto_rawDesc = "" + @@ -4226,7 +4271,9 @@ const file_solana_proto_rawDesc = "" + "filterName\"\x1c\n" + "\x1aUnregisterLogTrackingReply\"+\n" + "\x15GetLatestLPBlockReply\x12\x12\n" + - "\x04slot\x18\x01 \x01(\x04R\x04slot*\xb0\x01\n" + + "\x04slot\x18\x01 \x01(\x04R\x04slot\",\n" + + "\x14GetFiltersNamesReply\x12\x14\n" + + "\x05items\x18\x01 \x03(\tR\x05items*\xb0\x01\n" + "\fEncodingType\x12\x16\n" + "\x12ENCODING_TYPE_NONE\x10\x00\x12\x18\n" + "\x14ENCODING_TYPE_BASE58\x10\x01\x12\x18\n" + @@ -4247,7 +4294,7 @@ const file_solana_proto_rawDesc = "" + "\bTxStatus\x12\x13\n" + "\x0fTX_STATUS_FATAL\x10\x00\x12\x15\n" + "\x11TX_STATUS_ABORTED\x10\x01\x12\x15\n" + - "\x11TX_STATUS_SUCCESS\x10\x022\xad\n" + + "\x11TX_STATUS_SUCCESS\x10\x022\xfb\n" + "\n" + "\x06Solana\x12n\n" + "\x16GetAccountInfoWithOpts\x12*.loop.solana.GetAccountInfoWithOptsRequest\x1a(.loop.solana.GetAccountInfoWithOptsReply\x12J\n" + @@ -4265,7 +4312,8 @@ const file_solana_proto_rawDesc = "" + "SimulateTX\x12\x1e.loop.solana.SimulateTXRequest\x1a\x1c.loop.solana.SimulateTXReply\x12_\n" + "\x11SubmitTransaction\x12%.loop.solana.SubmitTransactionRequest\x1a#.loop.solana.SubmitTransactionReply\x12k\n" + "\x15UnregisterLogTracking\x12).loop.solana.UnregisterLogTrackingRequest\x1a'.loop.solana.UnregisterLogTrackingReply\x12N\n" + - "\x10GetLatestLPBlock\x12\x16.google.protobuf.Empty\x1a\".loop.solana.GetLatestLPBlockReplyB@Z>github.com/smartcontractkit/chainlink-common/pkg/chains/solanab\x06proto3" + "\x10GetLatestLPBlock\x12\x16.google.protobuf.Empty\x1a\".loop.solana.GetLatestLPBlockReply\x12L\n" + + "\x0fGetFiltersNames\x12\x16.google.protobuf.Empty\x1a!.loop.solana.GetFiltersNamesReplyB@Z>github.com/smartcontractkit/chainlink-common/pkg/chains/solanab\x06proto3" var ( file_solana_proto_rawDescOnce sync.Once @@ -4280,7 +4328,7 @@ func file_solana_proto_rawDescGZIP() []byte { } var file_solana_proto_enumTypes = make([]protoimpl.EnumInfo, 4) -var file_solana_proto_msgTypes = make([]protoimpl.MessageInfo, 61) +var file_solana_proto_msgTypes = make([]protoimpl.MessageInfo, 62) var file_solana_proto_goTypes = []any{ (EncodingType)(0), // 0: loop.solana.EncodingType (CommitmentType)(0), // 1: loop.solana.CommitmentType @@ -4347,16 +4395,17 @@ var file_solana_proto_goTypes = []any{ (*UnregisterLogTrackingRequest)(nil), // 62: loop.solana.UnregisterLogTrackingRequest (*UnregisterLogTrackingReply)(nil), // 63: loop.solana.UnregisterLogTrackingReply (*GetLatestLPBlockReply)(nil), // 64: loop.solana.GetLatestLPBlockReply - (*pb.BigInt)(nil), // 65: values.v1.BigInt - (chain_common.ComparisonOperator)(0), // 66: loop.chain.common.ComparisonOperator - (chain_common.BooleanOperator)(0), // 67: loop.chain.common.BooleanOperator - (*chain_common.Primitive)(nil), // 68: loop.chain.common.Primitive - (*chain_common.LimitAndSort)(nil), // 69: loop.chain.common.LimitAndSort - (*emptypb.Empty)(nil), // 70: google.protobuf.Empty + (*GetFiltersNamesReply)(nil), // 65: loop.solana.GetFiltersNamesReply + (*pb.BigInt)(nil), // 66: values.v1.BigInt + (chain_common.ComparisonOperator)(0), // 67: loop.chain.common.ComparisonOperator + (chain_common.BooleanOperator)(0), // 68: loop.chain.common.BooleanOperator + (*chain_common.Primitive)(nil), // 69: loop.chain.common.Primitive + (*chain_common.LimitAndSort)(nil), // 70: loop.chain.common.LimitAndSort + (*emptypb.Empty)(nil), // 71: google.protobuf.Empty } var file_solana_proto_depIdxs = []int32{ 6, // 0: loop.solana.Account.data:type_name -> loop.solana.DataBytesOrJSON - 65, // 1: loop.solana.Account.rent_epoch:type_name -> values.v1.BigInt + 66, // 1: loop.solana.Account.rent_epoch:type_name -> values.v1.BigInt 0, // 2: loop.solana.DataBytesOrJSON.encoding:type_name -> loop.solana.EncodingType 0, // 3: loop.solana.GetAccountInfoOpts.encoding:type_name -> loop.solana.EncodingType 1, // 4: loop.solana.GetAccountInfoOpts.commitment:type_name -> loop.solana.CommitmentType @@ -4401,17 +4450,17 @@ var file_solana_proto_depIdxs = []int32{ 3, // 43: loop.solana.SubmitTransactionReply.status:type_name -> loop.solana.TxStatus 5, // 44: loop.solana.SubmitTransactionRequest.cfg:type_name -> loop.solana.ComputeConfig 54, // 45: loop.solana.EventSig.hashed_value_comparers:type_name -> loop.solana.HashedValueComparator - 66, // 46: loop.solana.IndexedValueComparator.operator:type_name -> loop.chain.common.ComparisonOperator + 67, // 46: loop.solana.IndexedValueComparator.operator:type_name -> loop.chain.common.ComparisonOperator 49, // 47: loop.solana.EventBySubkey.value_comparers:type_name -> loop.solana.IndexedValueComparator 53, // 48: loop.solana.Expression.primitive:type_name -> loop.solana.Primitive 52, // 49: loop.solana.Expression.boolean_expression:type_name -> loop.solana.BooleanExpression - 67, // 50: loop.solana.BooleanExpression.boolean_operator:type_name -> loop.chain.common.BooleanOperator + 68, // 50: loop.solana.BooleanExpression.boolean_operator:type_name -> loop.chain.common.BooleanOperator 51, // 51: loop.solana.BooleanExpression.expression:type_name -> loop.solana.Expression - 68, // 52: loop.solana.Primitive.general_primitive:type_name -> loop.chain.common.Primitive + 69, // 52: loop.solana.Primitive.general_primitive:type_name -> loop.chain.common.Primitive 50, // 53: loop.solana.Primitive.event_by_subkey:type_name -> loop.solana.EventBySubkey 55, // 54: loop.solana.LPFilterQuery.subkey_paths:type_name -> loop.solana.Subkeys 51, // 55: loop.solana.QueryTrackedLogsRequest.filterQuery:type_name -> loop.solana.Expression - 69, // 56: loop.solana.QueryTrackedLogsRequest.limit_and_sort:type_name -> loop.chain.common.LimitAndSort + 70, // 56: loop.solana.QueryTrackedLogsRequest.limit_and_sort:type_name -> loop.chain.common.LimitAndSort 57, // 57: loop.solana.QueryTrackedLogsReply.logs:type_name -> loop.solana.Log 56, // 58: loop.solana.RegisterLogTrackingRequest.filter:type_name -> loop.solana.LPFilterQuery 10, // 59: loop.solana.Solana.GetAccountInfoWithOpts:input_type -> loop.solana.GetAccountInfoWithOptsRequest @@ -4427,23 +4476,25 @@ var file_solana_proto_depIdxs = []int32{ 44, // 69: loop.solana.Solana.SimulateTX:input_type -> loop.solana.SimulateTXRequest 47, // 70: loop.solana.Solana.SubmitTransaction:input_type -> loop.solana.SubmitTransactionRequest 62, // 71: loop.solana.Solana.UnregisterLogTracking:input_type -> loop.solana.UnregisterLogTrackingRequest - 70, // 72: loop.solana.Solana.GetLatestLPBlock:input_type -> google.protobuf.Empty - 9, // 73: loop.solana.Solana.GetAccountInfoWithOpts:output_type -> loop.solana.GetAccountInfoWithOptsReply - 11, // 74: loop.solana.Solana.GetBalance:output_type -> loop.solana.GetBalanceReply - 14, // 75: loop.solana.Solana.GetBlock:output_type -> loop.solana.GetBlockReply - 16, // 76: loop.solana.Solana.GetFeeForMessage:output_type -> loop.solana.GetFeeForMessageReply - 20, // 77: loop.solana.Solana.GetMultipleAccountsWithOpts:output_type -> loop.solana.GetMultipleAccountsWithOptsReply - 22, // 78: loop.solana.Solana.GetSignatureStatuses:output_type -> loop.solana.GetSignatureStatusesReply - 25, // 79: loop.solana.Solana.GetSlotHeight:output_type -> loop.solana.GetSlotHeightReply - 39, // 80: loop.solana.Solana.GetTransaction:output_type -> loop.solana.GetTransactionReply - 59, // 81: loop.solana.Solana.QueryTrackedLogs:output_type -> loop.solana.QueryTrackedLogsReply - 61, // 82: loop.solana.Solana.RegisterLogTracking:output_type -> loop.solana.RegisterLogTrackingReply - 43, // 83: loop.solana.Solana.SimulateTX:output_type -> loop.solana.SimulateTXReply - 46, // 84: loop.solana.Solana.SubmitTransaction:output_type -> loop.solana.SubmitTransactionReply - 63, // 85: loop.solana.Solana.UnregisterLogTracking:output_type -> loop.solana.UnregisterLogTrackingReply - 64, // 86: loop.solana.Solana.GetLatestLPBlock:output_type -> loop.solana.GetLatestLPBlockReply - 73, // [73:87] is the sub-list for method output_type - 59, // [59:73] is the sub-list for method input_type + 71, // 72: loop.solana.Solana.GetLatestLPBlock:input_type -> google.protobuf.Empty + 71, // 73: loop.solana.Solana.GetFiltersNames:input_type -> google.protobuf.Empty + 9, // 74: loop.solana.Solana.GetAccountInfoWithOpts:output_type -> loop.solana.GetAccountInfoWithOptsReply + 11, // 75: loop.solana.Solana.GetBalance:output_type -> loop.solana.GetBalanceReply + 14, // 76: loop.solana.Solana.GetBlock:output_type -> loop.solana.GetBlockReply + 16, // 77: loop.solana.Solana.GetFeeForMessage:output_type -> loop.solana.GetFeeForMessageReply + 20, // 78: loop.solana.Solana.GetMultipleAccountsWithOpts:output_type -> loop.solana.GetMultipleAccountsWithOptsReply + 22, // 79: loop.solana.Solana.GetSignatureStatuses:output_type -> loop.solana.GetSignatureStatusesReply + 25, // 80: loop.solana.Solana.GetSlotHeight:output_type -> loop.solana.GetSlotHeightReply + 39, // 81: loop.solana.Solana.GetTransaction:output_type -> loop.solana.GetTransactionReply + 59, // 82: loop.solana.Solana.QueryTrackedLogs:output_type -> loop.solana.QueryTrackedLogsReply + 61, // 83: loop.solana.Solana.RegisterLogTracking:output_type -> loop.solana.RegisterLogTrackingReply + 43, // 84: loop.solana.Solana.SimulateTX:output_type -> loop.solana.SimulateTXReply + 46, // 85: loop.solana.Solana.SubmitTransaction:output_type -> loop.solana.SubmitTransactionReply + 63, // 86: loop.solana.Solana.UnregisterLogTracking:output_type -> loop.solana.UnregisterLogTrackingReply + 64, // 87: loop.solana.Solana.GetLatestLPBlock:output_type -> loop.solana.GetLatestLPBlockReply + 65, // 88: loop.solana.Solana.GetFiltersNames:output_type -> loop.solana.GetFiltersNamesReply + 74, // [74:89] is the sub-list for method output_type + 59, // [59:74] is the sub-list for method input_type 59, // [59:59] is the sub-list for extension type_name 59, // [59:59] is the sub-list for extension extendee 0, // [0:59] is the sub-list for field type_name @@ -4485,7 +4536,7 @@ func file_solana_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_solana_proto_rawDesc), len(file_solana_proto_rawDesc)), NumEnums: 4, - NumMessages: 61, + NumMessages: 62, NumExtensions: 0, NumServices: 1, }, diff --git a/pkg/chains/solana/solana.proto b/pkg/chains/solana/solana.proto index c1f532f69b..f777780a07 100644 --- a/pkg/chains/solana/solana.proto +++ b/pkg/chains/solana/solana.proto @@ -22,6 +22,7 @@ service Solana { rpc SubmitTransaction(SubmitTransactionRequest) returns (SubmitTransactionReply); rpc UnregisterLogTracking(UnregisterLogTrackingRequest) returns (UnregisterLogTrackingReply); rpc GetLatestLPBlock(google.protobuf.Empty) returns (GetLatestLPBlockReply); + rpc GetFiltersNames(google.protobuf.Empty) returns (GetFiltersNamesReply); } // Account/tx data encodings. @@ -464,3 +465,8 @@ message UnregisterLogTrackingReply {} message GetLatestLPBlockReply { uint64 slot = 1; // block slot } + +// GetFiltersNames returns all registered filter names +message GetFiltersNamesReply { + repeated string items = 1; +} diff --git a/pkg/chains/solana/solana_grpc.pb.go b/pkg/chains/solana/solana_grpc.pb.go index 0ba218f75a..e86cee5bca 100644 --- a/pkg/chains/solana/solana_grpc.pb.go +++ b/pkg/chains/solana/solana_grpc.pb.go @@ -34,6 +34,7 @@ const ( Solana_SubmitTransaction_FullMethodName = "/loop.solana.Solana/SubmitTransaction" Solana_UnregisterLogTracking_FullMethodName = "/loop.solana.Solana/UnregisterLogTracking" Solana_GetLatestLPBlock_FullMethodName = "/loop.solana.Solana/GetLatestLPBlock" + Solana_GetFiltersNames_FullMethodName = "/loop.solana.Solana/GetFiltersNames" ) // SolanaClient is the client API for Solana service. @@ -54,6 +55,7 @@ type SolanaClient interface { SubmitTransaction(ctx context.Context, in *SubmitTransactionRequest, opts ...grpc.CallOption) (*SubmitTransactionReply, error) UnregisterLogTracking(ctx context.Context, in *UnregisterLogTrackingRequest, opts ...grpc.CallOption) (*UnregisterLogTrackingReply, error) GetLatestLPBlock(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetLatestLPBlockReply, error) + GetFiltersNames(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetFiltersNamesReply, error) } type solanaClient struct { @@ -204,6 +206,16 @@ func (c *solanaClient) GetLatestLPBlock(ctx context.Context, in *emptypb.Empty, return out, nil } +func (c *solanaClient) GetFiltersNames(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetFiltersNamesReply, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetFiltersNamesReply) + err := c.cc.Invoke(ctx, Solana_GetFiltersNames_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + // SolanaServer is the server API for Solana service. // All implementations must embed UnimplementedSolanaServer // for forward compatibility. @@ -222,6 +234,7 @@ type SolanaServer interface { SubmitTransaction(context.Context, *SubmitTransactionRequest) (*SubmitTransactionReply, error) UnregisterLogTracking(context.Context, *UnregisterLogTrackingRequest) (*UnregisterLogTrackingReply, error) GetLatestLPBlock(context.Context, *emptypb.Empty) (*GetLatestLPBlockReply, error) + GetFiltersNames(context.Context, *emptypb.Empty) (*GetFiltersNamesReply, error) mustEmbedUnimplementedSolanaServer() } @@ -274,6 +287,9 @@ func (UnimplementedSolanaServer) UnregisterLogTracking(context.Context, *Unregis func (UnimplementedSolanaServer) GetLatestLPBlock(context.Context, *emptypb.Empty) (*GetLatestLPBlockReply, error) { return nil, status.Errorf(codes.Unimplemented, "method GetLatestLPBlock not implemented") } +func (UnimplementedSolanaServer) GetFiltersNames(context.Context, *emptypb.Empty) (*GetFiltersNamesReply, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetFiltersNames not implemented") +} func (UnimplementedSolanaServer) mustEmbedUnimplementedSolanaServer() {} func (UnimplementedSolanaServer) testEmbeddedByValue() {} @@ -547,6 +563,24 @@ func _Solana_GetLatestLPBlock_Handler(srv interface{}, ctx context.Context, dec return interceptor(ctx, in, info, handler) } +func _Solana_GetFiltersNames_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(emptypb.Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SolanaServer).GetFiltersNames(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Solana_GetFiltersNames_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SolanaServer).GetFiltersNames(ctx, req.(*emptypb.Empty)) + } + return interceptor(ctx, in, info, handler) +} + // Solana_ServiceDesc is the grpc.ServiceDesc for Solana service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -610,6 +644,10 @@ var Solana_ServiceDesc = grpc.ServiceDesc{ MethodName: "GetLatestLPBlock", Handler: _Solana_GetLatestLPBlock_Handler, }, + { + MethodName: "GetFiltersNames", + Handler: _Solana_GetFiltersNames_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "solana.proto", diff --git a/pkg/loop/internal/relayer/solana.go b/pkg/loop/internal/relayer/solana.go index 491a4935ba..5d5c9ec302 100644 --- a/pkg/loop/internal/relayer/solana.go +++ b/pkg/loop/internal/relayer/solana.go @@ -36,6 +36,15 @@ func (sc *SolClient) GetLatestLPBlock(ctx context.Context) (*solana.LPBlock, err }, nil } +func (sc *SolClient) GetFiltersNames(ctx context.Context) ([]string, error) { + resp, err := sc.grpcClient.GetFiltersNames(ctx, &emptypb.Empty{}) + if err != nil { + return nil, net.WrapRPCErr(err) + } + + return resp.GetItems(), nil +} + func (sc *SolClient) SubmitTransaction(ctx context.Context, req solana.SubmitTransactionRequest) (*solana.SubmitTransactionReply, error) { pReq := solpb.ConvertSubmitTransactionRequestToProto(req) @@ -240,6 +249,17 @@ func (s *solServer) GetLatestLPBlock(ctx context.Context, _ *emptypb.Empty) (*so }, nil } +func (s *solServer) GetFiltersNames(ctx context.Context, _ *emptypb.Empty) (*solpb.GetFiltersNamesReply, error) { + names, err := s.impl.GetFiltersNames(ctx) + if err != nil { + return nil, net.WrapRPCErr(err) + } + + return &solpb.GetFiltersNamesReply{ + Items: names, + }, nil +} + func (s *solServer) SubmitTransaction(ctx context.Context, req *solpb.SubmitTransactionRequest) (*solpb.SubmitTransactionReply, error) { dReq, err := solpb.ConvertSubmitTransactionRequestFromProto(req) if err != nil { diff --git a/pkg/loop/internal/relayerset/solana.go b/pkg/loop/internal/relayerset/solana.go index 563ee8ff92..30e638e2a1 100644 --- a/pkg/loop/internal/relayerset/solana.go +++ b/pkg/loop/internal/relayerset/solana.go @@ -79,6 +79,10 @@ func (sc *solClient) UnregisterLogTracking(ctx context.Context, in *solpb.Unregi return sc.client.UnregisterLogTracking(appendRelayID(ctx, sc.relayID), in, opts...) } +func (sc *solClient) GetFiltersNames(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*solpb.GetFiltersNamesReply, error) { + return sc.client.GetFiltersNames(appendRelayID(ctx, sc.relayID), in, opts...) +} + type solServer struct { solpb.UnimplementedSolanaServer parent *Server @@ -344,6 +348,22 @@ func (ss *solServer) SimulateTX(ctx context.Context, req *solpb.SimulateTXReques return solpb.ConvertSimulateTXReplyToProto(dResp), nil } +func (ss *solServer) GetFiltersNames(ctx context.Context, _ *emptypb.Empty) (*solpb.GetFiltersNamesReply, error) { + solService, err := ss.parent.getSolService(ctx) + if err != nil { + return nil, err + } + + names, err := solService.GetFiltersNames(ctx) + if err != nil { + return nil, net.WrapRPCErr(err) + } + + return &solpb.GetFiltersNamesReply{ + Items: names, + }, nil +} + func (s *Server) getSolService(ctx context.Context) (types.SolanaService, error) { id, err := readRelayID(ctx) if err != nil { diff --git a/pkg/types/mocks/solana_service.go b/pkg/types/mocks/solana_service.go index 5ece5720f4..51310cccfc 100644 --- a/pkg/types/mocks/solana_service.go +++ b/pkg/types/mocks/solana_service.go @@ -260,6 +260,64 @@ func (_c *SolanaService_GetFeeForMessage_Call) RunAndReturn(run func(context.Con return _c } +// GetFiltersNames provides a mock function with given fields: ctx +func (_m *SolanaService) GetFiltersNames(ctx context.Context) ([]string, error) { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for GetFiltersNames") + } + + var r0 []string + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) ([]string, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) []string); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]string) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// SolanaService_GetFiltersNames_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetFiltersNames' +type SolanaService_GetFiltersNames_Call struct { + *mock.Call +} + +// GetFiltersNames is a helper method to define mock.On call +// - ctx context.Context +func (_e *SolanaService_Expecter) GetFiltersNames(ctx interface{}) *SolanaService_GetFiltersNames_Call { + return &SolanaService_GetFiltersNames_Call{Call: _e.mock.On("GetFiltersNames", ctx)} +} + +func (_c *SolanaService_GetFiltersNames_Call) Run(run func(ctx context.Context)) *SolanaService_GetFiltersNames_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *SolanaService_GetFiltersNames_Call) Return(_a0 []string, _a1 error) *SolanaService_GetFiltersNames_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *SolanaService_GetFiltersNames_Call) RunAndReturn(run func(context.Context) ([]string, error)) *SolanaService_GetFiltersNames_Call { + _c.Call.Return(run) + return _c +} + // GetLatestLPBlock provides a mock function with given fields: ctx func (_m *SolanaService) GetLatestLPBlock(ctx context.Context) (*solana.LPBlock, error) { ret := _m.Called(ctx) diff --git a/pkg/types/relayer.go b/pkg/types/relayer.go index f848834c8b..3e3da08d2f 100644 --- a/pkg/types/relayer.go +++ b/pkg/types/relayer.go @@ -253,6 +253,9 @@ type SolanaService interface { // GetLatestLPBlock retrieves current LatestBlock from cache perspective GetLatestLPBlock(ctx context.Context) (*solana.LPBlock, error) + + // GetFiltersNames returns all registered filters' names for later pruning + GetFiltersNames(ctx context.Context) ([]string, error) } // Relayer extends ChainService with providers for each product. @@ -537,3 +540,6 @@ func (uss *UnimplementedSolanaService) SimulateTX(ctx context.Context, req solan func (uss *UnimplementedSolanaService) GetLatestLPBlock(ctx context.Context) (*solana.LPBlock, error) { return nil, status.Errorf(codes.Unimplemented, "method GetLatestLPBlock not implemented") } +func (uss *UnimplementedSolanaService) GetFiltersNames(ctx context.Context) ([]string, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetFiltersNames not implemented") +}