ipld-eth-beacon-indexer/pkg/beaconclient/beaconclient.go

74 lines
3.3 KiB
Go
Raw Normal View History

package beaconclient
import (
"context"
"fmt"
"github.com/r3labs/sse"
log "github.com/sirupsen/logrus"
)
var (
bcHealthEndpoint = "/eth/v1/node/health" // Endpoint used for the healthcheck
bcHeadTopicEndpoint = "/eth/v1/events?topics=head" // Endpoint used to subscribe to the head of the chain
bcReorgTopicEndpoint = "/eth/v1/events?topics=chain_reorg" // Endpoint used to subscribe to the head of the chain
bcFinalizedTopicEndpoint = "/eth/v1/events?topics=finalized_checkpoint" // Endpoint used to subscribe to the head of the chain
connectionProtocol = "http"
)
// A struct that capture the Beacon Server that the Beacon Client will be interacting with and querying.
type BeaconClient struct {
Context context.Context // A context generic context with multiple uses.
ServerAddress string // Address of the Beacon Server
ServerPort int // Port of the Beacon Server
PerformHeadTracking bool // Should we track head?
PerformHistoricalProcessing bool // Should we perform historical processing?
HeadTracking *SseEvents[Head] // Track the head block
ReOrgTracking *SseEvents[ChainReorg] // Track all Reorgs
FinalizationTracking *SseEvents[FinalizedCheckpoint] // Track all finalization checkpoints
}
// A struct to keep track of relevant the head event topic.
type SseEvents[P ProcessedEvents] struct {
Url string // The url for the subscription. Primarily used for logging
MessagesCh chan *sse.Event // Contains all the messages from the SSE Channel
ErrorCh chan *SseError // Contains any errors while SSE streaming occurred
ProcessCh chan *P // Used to capture processed data in its proper struct.
SseClient *sse.Client // sse.Client object that is used to interact with the SSE stream
}
// An object to capture any errors when turning an SSE message to JSON.
type SseError struct {
err error
msg []byte
}
// A Function to create the BeaconClient.
func CreateBeaconClient(ctx context.Context, bcAddress string, bcPort int) *BeaconClient {
log.Info("Creating the BeaconClient")
return &BeaconClient{
Context: ctx,
ServerAddress: bcAddress,
ServerPort: bcPort,
HeadTracking: createSseEvent[Head](connectionProtocol, bcAddress, bcPort, bcHeadTopicEndpoint),
ReOrgTracking: createSseEvent[ChainReorg](connectionProtocol, bcAddress, bcPort, bcReorgTopicEndpoint),
FinalizationTracking: createSseEvent[FinalizedCheckpoint](connectionProtocol, bcAddress, bcPort, bcFinalizedTopicEndpoint),
}
}
// Create all the channels to handle a SSE events
func createSseEvent[P ProcessedEvents](connectionProtocol, bcAddress string, bcPort int, endpoint string) *SseEvents[P] {
url := fmt.Sprintf("%s://%s:%d%s", connectionProtocol, bcAddress, bcPort, endpoint)
sseEvents := &SseEvents[P]{
Url: url,
MessagesCh: make(chan *sse.Event),
ErrorCh: make(chan *SseError),
ProcessCh: make(chan *P),
SseClient: func(url string) *sse.Client {
log.WithFields(log.Fields{"url": url}).Info("Creating SSE client")
return sse.NewClient(url)
}(url),
}
return sseEvents
}