diff --git a/core/services/relay/solana/chain_reader.go b/core/services/relay/solana/chain_reader.go new file mode 100644 index 00000000000..1612d8a1a0a --- /dev/null +++ b/core/services/relay/solana/chain_reader.go @@ -0,0 +1,79 @@ +package solana + +import ( + "context" + "errors" + "fmt" + + commonservices "github.com/smartcontractkit/chainlink-common/pkg/services" + commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" + + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services" +) + +const ServiceName = "SolanaChainReader" + +type SolanaChainReaderService struct { + lggr logger.Logger + commonservices.StateMachine +} + +var ( + ErrUnimplemented = errors.New("function unimplemented") + _ services.ServiceCtx = &SolanaChainReaderService{} + _ commontypes.ChainReader = &SolanaChainReaderService{} +) + +// NewChainReaderService is a constructor for a new ChainReaderService for Solana. Returns a nil service on error. +func NewChainReaderService(lggr logger.Logger) (*SolanaChainReaderService, error) { + return &SolanaChainReaderService{ + lggr: lggr.Named(ServiceName), + }, nil +} + +// Name implements the services.ServiceCtx interface and returns the logger service name. +func (s *SolanaChainReaderService) Name() string { + return s.lggr.Name() +} + +// Start implements the services.ServiceCtx interface and starts necessary background services. +// An error is returned if starting any internal services fails. Subsequent calls to Start return +// and error. +func (s *SolanaChainReaderService) Start(_ context.Context) error { + return s.StartOnce(ServiceName, func() error { + return nil + }) +} + +// Close implements the services.ServiceCtx interface and stops all background services and cleans +// up used resources. Subsequent calls to Close return an error. +func (s *SolanaChainReaderService) Close() error { + return s.StopOnce(ServiceName, func() error { + return nil + }) +} + +// Ready implements the services.ServiceCtx interface and returns an error if starting the service +// encountered any errors or if the service is not ready to serve requests. +func (s *SolanaChainReaderService) Ready() error { + return s.StateMachine.Ready() +} + +// HealthReport implements the services.ServiceCtx interface and returns errors for any internal +// function or service that may have failed. +func (s *SolanaChainReaderService) HealthReport() map[string]error { + return map[string]error{s.Name(): s.Healthy()} +} + +// GetLatestValue implements the types.ChainReader interface and requests and parses on-chain +// data named by the provided contract, method, and params. +func (s *SolanaChainReaderService) GetLatestValue(_ context.Context, contractName, method string, params any, returnVal any) error { + return fmt.Errorf("%w: GetLatestValue not available", ErrUnimplemented) +} + +// Bind implements the types.ChainReader interface and allows new contract bindings to be added +// to the service. +func (s *SolanaChainReaderService) Bind(_ context.Context, bindings []commontypes.BoundContract) error { + return fmt.Errorf("%w: Bind not available", ErrUnimplemented) +} diff --git a/core/services/relay/solana/chain_reader_test.go b/core/services/relay/solana/chain_reader_test.go new file mode 100644 index 00000000000..f0092bfb246 --- /dev/null +++ b/core/services/relay/solana/chain_reader_test.go @@ -0,0 +1,36 @@ +package solana_test + +import ( + "testing" + + "github.com/test-go/testify/require" + + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/solana" +) + +func TestSolanaChainReaderService_ServiceCtx(t *testing.T) { + t.Parallel() + + ctx := testutils.Context(t) + svc, err := solana.NewChainReaderService(logger.TestLogger(t)) + + require.NoError(t, err) + require.NotNil(t, svc) + + require.Error(t, svc.Ready()) + require.Len(t, svc.HealthReport(), 1) + require.Contains(t, svc.HealthReport(), solana.ServiceName) + require.Error(t, svc.HealthReport()[solana.ServiceName]) + + require.NoError(t, svc.Start(ctx)) + require.NoError(t, svc.Ready()) + require.Equal(t, map[string]error{solana.ServiceName: nil}, svc.HealthReport()) + + require.Error(t, svc.Start(ctx)) + + require.NoError(t, svc.Close()) + require.Error(t, svc.Ready()) + require.Error(t, svc.Close()) +}