Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"lido-events/internal/adapters/storage/exits"
"lido-events/internal/adapters/storage/performance"
"lido-events/internal/adapters/vebo"
"lido-events/internal/application/domain"
"lido-events/internal/application/services"
"lido-events/internal/config"
"lido-events/internal/logger"
Expand All @@ -40,6 +41,9 @@ func main() {
logger.FatalWithPrefix(logPrefix, "Failed to load network configuration: %v", err)
}

// Initialize domain-level notification identifiers based on network
domain.InitNotifications(config.Network)

// Initiate RPC Ethereum clients
rpcClient, err := ethclient.Dial(config.RpcUrl)
if err != nil {
Expand All @@ -54,7 +58,7 @@ func main() {
if err != nil {
logger.FatalWithPrefix(logPrefix, "Failed to initialize performance storage adapter: %v", err)
}
notifier := notifier.NewNotifier(config.Network, config.LidoDnpName, config.BrainUrl, config.StakersUiUrl, config.BeaconchaUrl)
notifier := notifier.NewNotifier(ctx, config.Network, config.DappmanagerUrl, config.LidoDnpName, config.BrainUrl, config.StakersUiUrl, config.BeaconchaUrl)

relays, err := relays.NewARelays(rpcClient, config.MEVBoostRelaysAllowListAddres, config.DappmanagerUrl, config.MevBoostDnpName)
if err != nil {
Expand Down
99 changes: 0 additions & 99 deletions internal/adapters/dappmanager/dappmanager.go

This file was deleted.

139 changes: 139 additions & 0 deletions internal/adapters/notifier/dappmanager/dappmanager.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
package dappmanager

import (
"context"
"encoding/json"
"fmt"
"net/http"

"lido-events/internal/application/domain"
)

// DappManager is the adapter to interact with the DappManager API
type DappManager struct {
baseURL string
lidoDnpName string
client *http.Client
}

// NewDappManager creates a new DappManager instance
func NewDappManager(baseURL string, dnpName string) *DappManager {
return &DappManager{
baseURL: baseURL,
lidoDnpName: dnpName,
client: &http.Client{},
}
}

// Manifest represents the manifest of a package
type manifest struct {
Notifications struct {
CustomEndpoints []CustomEndpoint `json:"customEndpoints"`
} `json:"notifications"`
}

type CustomEndpoint struct {
Name string `json:"name"`
Enabled bool `json:"enabled"`
Description string `json:"description"`
IsBanner bool `json:"isBanner"`
CorrelationId string `json:"correlationId"`
Metric *struct {
Treshold float64 `json:"treshold"`
Min float64 `json:"min"`
Max float64 `json:"max"`
Unit string `json:"unit"`
} `json:"metric,omitempty"`
}

// getNotificationsEnabled retrieves the notifications from the DappManager API
func (d *DappManager) getNotificationsEnabled(ctx context.Context) (domain.LidoNotificationsEnabled, error) {
customEndpoints, err := d.getLidoManifestNotifications(ctx)
if err != nil {
return nil, fmt.Errorf("failed to get notifications from signer manifest: %w", err)
}

notifications := make(domain.LidoNotificationsEnabled)
for _, endpoint := range customEndpoints {
notifications[domain.LidoNotification(endpoint.CorrelationId)] = endpoint.Enabled
}

return notifications, nil
}

// isNotificationEnabled is a generic helper that checks whether a given
// notification (identified by its LidoNotification key) is enabled according
// to the signer manifest configuration retrieved from DappManager.
func (d *DappManager) isNotificationEnabled(ctx context.Context, notification domain.LidoNotification) (bool, error) {
notifications, err := d.getNotificationsEnabled(ctx)
if err != nil {
return false, err
}

enabled, ok := notifications[notification]
if !ok {
return false, nil
}

return enabled, nil
}

// IsValidatorExitRequestEnabled reports whether the validator exit request
// notification (correlationId like "<network>-validator-exit-request") is
// enabled in the signer manifest.
func (d *DappManager) IsValidatorExitRequestEnabled(ctx context.Context) (bool, error) {
return d.isNotificationEnabled(ctx, domain.Notifications.ValidatorExitRequest)
}

// IsValidatorExitEnabled reports whether the validator exit notification
// (correlationId like "<network>-validator-exit") is enabled.
func (d *DappManager) IsValidatorExitEnabled(ctx context.Context) (bool, error) {
return d.isNotificationEnabled(ctx, domain.Notifications.ValidatorExit)
}

// IsRelaysBlacklistEnabled reports whether the relays blacklist notification
// (correlationId like "<network>-relays-blacklist") is enabled.
func (d *DappManager) IsRelaysBlacklistEnabled(ctx context.Context) (bool, error) {
return d.isNotificationEnabled(ctx, domain.Notifications.RelaysBlacklist)
}

// IsRelaysMissingEnabled reports whether the relays missing notification
// (correlationId like "<network>-relays-missing") is enabled.
func (d *DappManager) IsRelaysMissingEnabled(ctx context.Context) (bool, error) {
return d.isNotificationEnabled(ctx, domain.Notifications.RleaysMissing)
}

// IsMissingLogReceiptsEnabled reports whether the missing log receipts
// notification (correlationId like "<network>-missing-log-receipts") is
// enabled.
func (d *DappManager) IsMissingLogReceiptsEnabled(ctx context.Context) (bool, error) {
return d.isNotificationEnabled(ctx, domain.Notifications.MissingLogReceipts)
}

// getLidoManifestNotifications gets the notifications from the Signer package manifest
func (d *DappManager) getLidoManifestNotifications(ctx context.Context) ([]CustomEndpoint, error) {
url := d.baseURL + "/package-manifest/" + d.lidoDnpName

req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return nil, fmt.Errorf("failed to create request for package %s: %w", d.lidoDnpName, err)
}

resp, err := d.client.Do(req)
if err != nil {
return nil, fmt.Errorf("failed to fetch manifest for package %s: %w", d.lidoDnpName, err)
}
defer resp.Body.Close()

// This covers all 2xx status codes. If its not 2xx, we dont bother parsing the manifest and return an error
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
return nil, fmt.Errorf("unexpected status code %d for package %s", resp.StatusCode, d.lidoDnpName)
}

var manifest manifest
if err := json.NewDecoder(resp.Body).Decode(&manifest); err != nil {
return nil, fmt.Errorf("failed to decode manifest for package %s: %w", d.lidoDnpName, err)
}

return manifest.Notifications.CustomEndpoints, nil
}
Loading