diff --git a/backend/pkg/api/data_access/mobile.go b/backend/pkg/api/data_access/mobile.go
index 6d585b2caa..50a1a66959 100644
--- a/backend/pkg/api/data_access/mobile.go
+++ b/backend/pkg/api/data_access/mobile.go
@@ -173,7 +173,8 @@ func (d *DataAccessService) GetValidatorDashboardMobileWidget(ctx context.Contex
if err != nil {
return nil, fmt.Errorf("error retrieving validator dashboard overview data: %w", err)
}
- data.NetworkEfficiency = efficiency.TotalEfficiency[enums.AllTime].Float64
+ networkEfficiency := efficiency.TotalEfficiency[enums.AllTime].Float64
+ data.NetworkEfficiency = &networkEfficiency
// Validator status
eg.Go(func() error {
@@ -251,23 +252,31 @@ func (d *DataAccessService) GetValidatorDashboardMobileWidget(ctx context.Contex
share := queryResult.EffectiveRPLStake.Div(rpNetworkStats.EffectiveRPLStaked)
periodsPerYear := decimal.NewFromFloat(365 / (rpNetworkStats.ClaimIntervalHours / 24))
- data.RplApr = rpNetworkStats.NodeOperatorRewards.
+ rplApr := rpNetworkStats.NodeOperatorRewards.
Mul(share).
Div(queryResult.RPLStake).
Mul(periodsPerYear).InexactFloat64()
+ data.RplApr = &rplApr
}
return nil
})
- retrieveApr := func(timeFrame enums.TimePeriod, apr *float64) {
- eg.Go(func() error {
- incomeInfo, err := d.getElClAPR(ctx, wrappedDashboardId, -1, timeFrame)
- if err != nil {
- return err
- }
- *apr = incomeInfo.Apr.El + incomeInfo.Apr.Cl
- return nil
- })
+ retrieveApr := func(timeFrame enums.TimePeriod) (*float64, error) {
+ incomeInfo, err := d.getElClAPR(ctx, wrappedDashboardId, -1, timeFrame)
+ if err != nil {
+ return nil, err
+ }
+ if incomeInfo.Apr.El == nil && incomeInfo.Apr.Cl == nil {
+ return nil, nil
+ }
+ var totalApr float64
+ if incomeInfo.Apr.El != nil {
+ totalApr += *incomeInfo.Apr.El
+ }
+ if incomeInfo.Apr.Cl != nil {
+ totalApr += *incomeInfo.Apr.Cl
+ }
+ return &totalApr, nil
}
retrieveRewards := func(timeFrame enums.TimePeriod, rewards *t.ClElValue[decimal.Decimal]) {
@@ -281,27 +290,42 @@ func (d *DataAccessService) GetValidatorDashboardMobileWidget(ctx context.Contex
})
}
- retrieveEfficiency := func(table string, efficiency *float64) {
- eg.Go(func() error {
- ds := goqu.Dialect("postgres").
- From(goqu.L(fmt.Sprintf(`%s AS r`, table))).
- With("validators", goqu.L("(SELECT dashboard_id, validator_index FROM users_val_dashboards_validators WHERE dashboard_id = ?)", dashboardId)).
- Select(
- goqu.L("COALESCE(SUM(efficiency_dividend::Int256) / NULLIF(SUM(efficiency_divisor::Int256), 0), 0)").As("efficiency"),
- ).
- InnerJoin(goqu.L("validators v"), goqu.On(goqu.L("r.validator_index = v.validator_index"))).
- Where(goqu.L("r.validator_index IN (SELECT validator_index FROM validators)"))
+ retrieveEfficiency := func(table string) (*float64, error) {
+ ds := goqu.Dialect("postgres").
+ From(goqu.L(fmt.Sprintf(`%s AS r`, table))).
+ With("validators", goqu.L("(SELECT dashboard_id, validator_index FROM users_val_dashboards_validators WHERE dashboard_id = ?)", dashboardId)).
+ Select(
+ goqu.L("SUM(efficiency_dividend::decimal)").As("efficiency_dividend"),
+ goqu.L("SUM(efficiency_divisor::decimal)").As("efficiency_divisor"),
+ ).
+ InnerJoin(goqu.L("validators v"), goqu.On(goqu.L("r.validator_index = v.validator_index"))).
+ Where(goqu.L("r.validator_index IN (SELECT validator_index FROM validators)"))
+
+ type dbResult struct {
+ EfficiencyDividend decimal.Decimal `db:"efficiency_dividend"`
+ EfficiencyDivisor decimal.Decimal `db:"efficiency_divisor"`
+ }
+ dbRes, err := runQuery[dbResult](ctx, d.clickhouseReader, ds)
- *efficiency, err = runQuery[float64](ctx, d.clickhouseReader, ds)
+ var efficiency *float64
+ if !dbRes.EfficiencyDivisor.IsZero() {
+ eff := dbRes.EfficiencyDividend.Div(dbRes.EfficiencyDivisor).InexactFloat64()
+ efficiency = &eff
+ }
- return err
- })
+ return efficiency, err
}
retrieveRewards(enums.Last24h, &data.Last24hIncome)
retrieveRewards(enums.Last7d, &data.Last7dIncome)
- retrieveApr(enums.Last30d, &data.Last30dApr)
- retrieveEfficiency("validator_dashboard_data_rolling_30d", &data.Last30dEfficiency)
+ eg.Go(func() error {
+ data.Last30dApr, err = retrieveApr(enums.Last30d)
+ return err
+ })
+ eg.Go(func() error {
+ data.Last30dEfficiency, err = retrieveEfficiency("validator_dashboard_data_rolling_30d")
+ return err
+ })
err = eg.Wait()
diff --git a/backend/pkg/api/data_access/vdb_helpers.go b/backend/pkg/api/data_access/vdb_helpers.go
index 5cbe593b79..33e4290f95 100644
--- a/backend/pkg/api/data_access/vdb_helpers.go
+++ b/backend/pkg/api/data_access/vdb_helpers.go
@@ -117,7 +117,7 @@ func (d *DataAccessService) getTotalRewardsColumns() string {
type IncomeInfo struct {
Rewards t.ClElValue[decimal.Decimal]
- Apr t.ClElValue[float64]
+ Apr t.ClElValue[*float64]
}
func (d *DataAccessService) getElClAPR(ctx context.Context, dashboardId t.VDBId, groupId int64, timeFrame enums.TimePeriod) (rewardsApr IncomeInfo, err error) {
@@ -208,12 +208,17 @@ func (d *DataAccessService) getElClAPR(ctx context.Context, dashboardId t.VDBId,
}
// precondition: invested amount and rewards are in the same currency
-func calcAPR(rewards, cumulativeDivisor decimal.Decimal, duration time.Duration) float64 {
+func calcAPR(rewards, cumulativeDivisor decimal.Decimal, duration time.Duration) *float64 {
+ if cumulativeDivisor.IsZero() {
+ return nil
+ }
+ var apr float64
if rewards.IsZero() || cumulativeDivisor.IsZero() || duration.Nanoseconds() == 0 {
- return 0
+ return &apr
}
annualizationFactor := decimal.NewFromInt(utils.Year.Nanoseconds()).Div(decimal.NewFromInt(duration.Nanoseconds()))
- return rewards.Div(cumulativeDivisor).Mul(annualizationFactor).InexactFloat64()
+ apr = rewards.Div(cumulativeDivisor).Mul(annualizationFactor).InexactFloat64()
+ return &apr
}
// converts a cl amount to the main currency
diff --git a/backend/pkg/api/data_access/vdb_management.go b/backend/pkg/api/data_access/vdb_management.go
index 1ec93fa7c1..088b49d580 100644
--- a/backend/pkg/api/data_access/vdb_management.go
+++ b/backend/pkg/api/data_access/vdb_management.go
@@ -377,49 +377,86 @@ func (d *DataAccessService) GetValidatorDashboardOverview(ctx context.Context, d
return nil
})
- retrieveRewardsAndEfficiency := func(timeFrame enums.TimePeriod, rewards *t.ClElValue[decimal.Decimal], apr *t.ClElValue[float64], efficiency *float64) {
- // Rewards + APR
- eg.Go(func() error {
- incomeInfo, err := d.getElClAPR(ctx, dashboardId, -1, timeFrame)
- if err != nil {
- return err
- }
- *rewards = incomeInfo.Rewards
- *apr = incomeInfo.Apr
- return nil
- })
+ retrieveRewards := func(timeFrame enums.TimePeriod) (rewards t.ClElValue[decimal.Decimal], apr t.ClElValue[*float64], err error) {
+ incomeInfo, err := d.getElClAPR(ctx, dashboardId, -1, timeFrame)
+ rewards = incomeInfo.Rewards
+ apr = incomeInfo.Apr
+ return
+ }
- // Efficiency
- eg.Go(func() error {
- table, err := timeFrame.Table()
- if err != nil {
- return err
- }
- ds := goqu.Dialect("postgres").
- From(goqu.L(fmt.Sprintf(`%s AS r`, table))).
- With("validators", goqu.L("(SELECT dashboard_id, validator_index FROM users_val_dashboards_validators WHERE dashboard_id = ?)", dashboardId.Id)).
- Select(
- goqu.L("COALESCE(SUM(efficiency_dividend::Int256) / NULLIF(SUM(efficiency_divisor::Int256), 0), 0)").As("efficiency"),
- )
-
- if len(dashboardId.Validators) == 0 {
- ds = ds.
- InnerJoin(goqu.L("validators v"), goqu.On(goqu.L("r.validator_index = v.validator_index"))).
- Where(goqu.L("r.validator_index IN (SELECT validator_index FROM validators)"))
- } else {
- ds = ds.
- Where(goqu.L("r.validator_index IN ?", dashboardId.Validators))
- }
+ retrieveEfficiency := func(timeFrame enums.TimePeriod) (efficiency *float64, err error) {
+ table, err := timeFrame.Table()
+ if err != nil {
+ return
+ }
+ ds := goqu.Dialect("postgres").
+ From(goqu.L(fmt.Sprintf(`%s AS r`, table))).
+ With("validators", goqu.L("(SELECT dashboard_id, validator_index FROM users_val_dashboards_validators WHERE dashboard_id = ?)", dashboardId.Id)).
+ Select(
+ goqu.L("SUM(efficiency_dividend::decimal)").As("efficiency_dividend"),
+ goqu.L("SUM(efficiency_divisor::decimal)").As("efficiency_divisor"),
+ )
+
+ if len(dashboardId.Validators) == 0 {
+ ds = ds.
+ InnerJoin(goqu.L("validators v"), goqu.On(goqu.L("r.validator_index = v.validator_index"))).
+ Where(goqu.L("r.validator_index IN (SELECT validator_index FROM validators)"))
+ } else {
+ ds = ds.
+ Where(goqu.L("r.validator_index IN ?", dashboardId.Validators))
+ }
- *efficiency, err = runQuery[float64](ctx, d.clickhouseReader, ds)
- return err
- })
+ type dbResult struct {
+ EfficiencyDividend decimal.Decimal `db:"efficiency_dividend"`
+ EfficiencyDivisor decimal.Decimal `db:"efficiency_divisor"`
+ }
+ dbRes, err := runQuery[dbResult](ctx, d.clickhouseReader, ds)
+ if !dbRes.EfficiencyDivisor.IsZero() {
+ eff := dbRes.EfficiencyDividend.Div(dbRes.EfficiencyDivisor).InexactFloat64()
+ efficiency = &eff
+ }
+ return
}
- retrieveRewardsAndEfficiency(enums.Last24h, &data.Rewards.Last24h, &data.Apr.Last24h, &data.Efficiency.Last24h)
- retrieveRewardsAndEfficiency(enums.Last7d, &data.Rewards.Last7d, &data.Apr.Last7d, &data.Efficiency.Last7d)
- retrieveRewardsAndEfficiency(enums.Last30d, &data.Rewards.Last30d, &data.Apr.Last30d, &data.Efficiency.Last30d)
- retrieveRewardsAndEfficiency(enums.AllTime, &data.Rewards.AllTime, &data.Apr.AllTime, &data.Efficiency.AllTime)
+ // last 24h
+ eg.Go(func() error {
+ data.Rewards.Last24h, data.Apr.Last24h, err = retrieveRewards(enums.Last24h)
+ return err
+ })
+ eg.Go(func() error {
+ data.Efficiency.Last24h, err = retrieveEfficiency(enums.Last24h)
+ return err
+ })
+
+ // last 7d
+ eg.Go(func() error {
+ data.Rewards.Last7d, data.Apr.Last7d, err = retrieveRewards(enums.Last7d)
+ return err
+ })
+ eg.Go(func() error {
+ data.Efficiency.Last7d, err = retrieveEfficiency(enums.Last7d)
+ return err
+ })
+
+ // last 30d
+ eg.Go(func() error {
+ data.Rewards.Last30d, data.Apr.Last30d, err = retrieveRewards(enums.Last30d)
+ return err
+ })
+ eg.Go(func() error {
+ data.Efficiency.Last30d, err = retrieveEfficiency(enums.Last30d)
+ return err
+ })
+
+ // all time
+ eg.Go(func() error {
+ data.Rewards.AllTime, data.Apr.AllTime, err = retrieveRewards(enums.AllTime)
+ return err
+ })
+ eg.Go(func() error {
+ data.Efficiency.AllTime, err = retrieveEfficiency(enums.AllTime)
+ return err
+ })
err = eg.Wait()
diff --git a/backend/pkg/api/data_access/vdb_summary.go b/backend/pkg/api/data_access/vdb_summary.go
index 709fdcdb74..18c1ba089d 100644
--- a/backend/pkg/api/data_access/vdb_summary.go
+++ b/backend/pkg/api/data_access/vdb_summary.go
@@ -389,7 +389,10 @@ func (d *DataAccessService) GetValidatorDashboardSummary(ctx context.Context, da
}
case enums.VDBSummaryColumns.Efficiency:
sortParam = func(resultEntry t.VDBSummaryTableRow) float64 {
- return resultEntry.Efficiency
+ if resultEntry.Efficiency == nil {
+ return -1
+ }
+ return *resultEntry.Efficiency
}
case enums.VDBSummaryColumns.Attestations:
sortParam = func(resultEntry t.VDBSummaryTableRow) float64 {
@@ -741,23 +744,21 @@ func (d *DataAccessService) GetValidatorDashboardGroupSummary(ctx context.Contex
}
if totalBlockChance > 0 {
- ret.Luck.Proposal.Percent = (float64(totalBlocksScheduled)) / totalBlockChance
+ proposalLuck := (float64(totalBlocksScheduled)) / totalBlockChance
+ ret.Luck.Proposal.Percent = &proposalLuck
// calculate the average time it takes for the set of validators to propose a single block on average
ret.Luck.Proposal.AverageIntervalSeconds = uint64(time.Duration((luckHours / totalBlockChance) * float64(time.Hour)).Seconds())
ret.Luck.Proposal.ExpectedTimestamp = uint64(lastBlockTs.Unix()) + ret.Luck.Proposal.AverageIntervalSeconds
- } else {
- ret.Luck.Proposal.Percent = 0
}
- if totalSyncExpected == 0 {
- ret.Luck.Sync.Percent = 0
- } else {
+ if totalSyncExpected > 0 {
totalSyncSlotDuties := float64(ret.SyncCommittee.StatusCount.Failed) + float64(ret.SyncCommittee.StatusCount.Success)
slotDutiesPerSyncCommittee := float64(utils.SlotsPerSyncCommittee())
syncCommittees := math.Ceil(totalSyncSlotDuties / slotDutiesPerSyncCommittee) // gets the number of sync committees
- ret.Luck.Sync.Percent = syncCommittees / totalSyncExpected
+ syncLuck := syncCommittees / totalSyncExpected
+ ret.Luck.Sync.Percent = &syncLuck
// calculate the average time it takes for the set of validators to be elected into a sync committee on average
ret.Luck.Sync.AverageIntervalSeconds = uint64(time.Duration((luckHours / totalSyncExpected) * float64(time.Hour)).Seconds())
@@ -816,24 +817,16 @@ func (d *DataAccessService) GetValidatorDashboardGroupSummary(ctx context.Contex
return ret, nil
}
-func calcEfficiencyNulled(dividend, divisor decimal.Decimal) *float64 {
+func calcEfficiency(dividend, divisor decimal.Decimal) *float64 {
if divisor.IsZero() {
return nil
}
- efficiency := calcEfficiency(dividend, divisor)
- return &efficiency
-}
-
-func calcEfficiency(dividend, divisor decimal.Decimal) float64 {
- if divisor.IsZero() {
- return 1
- }
eff := dividend.Div(divisor).InexactFloat64()
if eff > 1 {
log.Error(nil, "efficiency is greater than 100%", 1, map[string]interface{}{"efficiency": eff})
eff = 1
}
- return eff
+ return &eff
}
// for summary charts: series id is group id, no stack
@@ -956,7 +949,7 @@ func (d *DataAccessService) GetValidatorDashboardSummaryChart(ctx context.Contex
}
if !dashboardId.AggregateGroups && requestedGroupsMap[row.GroupId] {
- eff := calcEfficiencyNulled(row.EfficiencyDividend, row.EfficiencyDivisor)
+ eff := calcEfficiency(row.EfficiencyDividend, row.EfficiencyDivisor)
if eff == nil {
continue
}
@@ -998,7 +991,7 @@ func (d *DataAccessService) GetValidatorDashboardSummaryChart(ctx context.Contex
totalLineGroupId = t.DefaultGroupId
}
for _, row := range totalEfficiencyMap {
- data[row.Timestamp][totalLineGroupId] = calcEfficiencyNulled(row.EfficiencyDividend, row.EfficiencyDivisor)
+ data[row.Timestamp][totalLineGroupId] = calcEfficiency(row.EfficiencyDividend, row.EfficiencyDivisor)
}
groupMap[totalLineGroupId] = true
}
diff --git a/backend/pkg/api/handlers/auth.go b/backend/pkg/api/handlers/auth.go
index 36f4d9799f..bf457e2cf7 100644
--- a/backend/pkg/api/handlers/auth.go
+++ b/backend/pkg/api/handlers/auth.go
@@ -196,7 +196,7 @@ func (h *HandlerService) GetUserIdByApiKey(r *http.Request) (uint64, error) {
return userId, err
}
-// if this is used, user ID should've been stored in context (by GetUserIdStoreMiddleware)
+// if this is used, user ID should've been stored in context (by StoreUserIdMiddleware)
func GetUserIdByContext(ctx context.Context) (uint64, error) {
userId, ok := ctx.Value(types.CtxUserIdKey).(uint64)
if !ok {
diff --git a/backend/pkg/api/types/common.go b/backend/pkg/api/types/common.go
index 004cadeb55..3747c09bcd 100644
--- a/backend/pkg/api/types/common.go
+++ b/backend/pkg/api/types/common.go
@@ -39,9 +39,9 @@ type Address struct {
}
type LuckItem struct {
- Percent float64 `json:"percent"`
- ExpectedTimestamp uint64 `json:"expected_timestamp"`
- AverageIntervalSeconds uint64 `json:"average_interval_seconds"`
+ Percent *float64 `json:"percent"`
+ ExpectedTimestamp uint64 `json:"expected_timestamp"`
+ AverageIntervalSeconds uint64 `json:"average_interval_seconds"`
}
type Luck struct {
diff --git a/backend/pkg/api/types/mobile.go b/backend/pkg/api/types/mobile.go
index 9c16b2fe2e..fa14366e29 100644
--- a/backend/pkg/api/types/mobile.go
+++ b/backend/pkg/api/types/mobile.go
@@ -13,11 +13,11 @@ type MobileWidgetData struct {
ValidatorStateCounts ValidatorStateCounts `json:"validator_state_counts"`
Last24hIncome ClElValue[decimal.Decimal] `json:"last_24h_income" faker:"eth"`
Last7dIncome ClElValue[decimal.Decimal] `json:"last_7d_income" faker:"eth"`
- Last30dApr float64 `json:"last_30d_apr"`
- Last30dEfficiency float64 `json:"last_30d_efficiency"`
- NetworkEfficiency float64 `json:"network_efficiency"`
+ Last30dApr *float64 `json:"last_30d_apr"`
+ Last30dEfficiency *float64 `json:"last_30d_efficiency"`
+ NetworkEfficiency *float64 `json:"network_efficiency"`
RplPrice decimal.Decimal `json:"rpl_price" faker:"eth"`
- RplApr float64 `json:"rpl_apr"`
+ RplApr *float64 `json:"rpl_apr"`
ELCLPrice float64 `json:"el_cl_price"`
}
diff --git a/backend/pkg/api/types/validator_dashboard.go b/backend/pkg/api/types/validator_dashboard.go
index 7b7824740d..a85b86ed55 100644
--- a/backend/pkg/api/types/validator_dashboard.go
+++ b/backend/pkg/api/types/validator_dashboard.go
@@ -25,9 +25,9 @@ type VDBOverviewData struct {
Network uint64 `json:"network"`
Groups []VDBOverviewGroup `json:"groups"`
Validators ValidatorStateCounts `json:"validators"`
- Efficiency PeriodicValues[float64] `json:"efficiency"`
+ Efficiency PeriodicValues[*float64] `json:"efficiency"`
Rewards PeriodicValues[ClElValue[decimal.Decimal]] `json:"rewards"`
- Apr PeriodicValues[ClElValue[float64]] `json:"apr"`
+ Apr PeriodicValues[ClElValue[*float64]] `json:"apr"`
ChartHistorySeconds ChartHistorySeconds `json:"chart_history_seconds"`
Balances ValidatorBalances `json:"balances"`
IsAboveEbLimit bool `json:"is_above_effective_balance_limit"` // refers to owner; relevant for shared dashboards
@@ -58,7 +58,7 @@ type VDBSummaryTableRow struct {
GroupId int64 `json:"group_id" extensions:"x-order=1"`
Status VDBSummaryStatus `json:"status"`
Validators VDBSummaryValidators `json:"validators"`
- Efficiency float64 `json:"efficiency"`
+ Efficiency *float64 `json:"efficiency"`
AverageNetworkEfficiency float64 `json:"average_network_efficiency"`
Attestations StatusCount `json:"attestations"`
Proposals StatusCount `json:"proposals"`
@@ -84,26 +84,26 @@ type VDBGroupSummaryMissedRewards struct {
Sync decimal.Decimal `json:"sync"`
}
type VDBGroupSummaryData struct {
- Efficiency float64 `json:"efficiency"`
+ Efficiency *float64 `json:"efficiency"`
Balances ValidatorBalances `json:"balances"`
Rewards ClElValue[decimal.Decimal] `json:"rewards"`
AttestationsHead StatusCount `json:"attestations_head"`
AttestationsSource StatusCount `json:"attestations_source"`
AttestationsTarget StatusCount `json:"attestations_target"`
- AttestationEfficiency float64 `json:"attestation_efficiency"`
+ AttestationEfficiency *float64 `json:"attestation_efficiency"`
AttestationAvgInclDist float64 `json:"attestation_avg_incl_dist"`
SyncCommittee VDBGroupSummaryColumnItem `json:"sync"`
SyncCommitteeCount VDBGroupSummarySyncCount `json:"sync_count"`
- SyncEfficiency float64 `json:"sync_efficiency"`
+ SyncEfficiency *float64 `json:"sync_efficiency"`
Slashings VDBGroupSummaryColumnItem `json:"slashings"` // Failed slashings are count of validators in the group that were slashed
ProposalValidators []uint64 `json:"proposal_validators"` // fill with up to 3 validator indexes
ProposalValidatorCount uint64 `json:"proposal_validator_count"` // number of distinct validators
- ProposalEfficiency float64 `json:"proposal_efficiency"`
+ ProposalEfficiency *float64 `json:"proposal_efficiency"`
MissedRewards VDBGroupSummaryMissedRewards `json:"missed_rewards"`
- Apr ClElValue[float64] `json:"apr"`
+ Apr ClElValue[*float64] `json:"apr"`
Luck Luck `json:"luck"`
diff --git a/frontend/types/api/common.ts b/frontend/types/api/common.ts
index 6b13482d14..3b657944df 100644
--- a/frontend/types/api/common.ts
+++ b/frontend/types/api/common.ts
@@ -32,7 +32,7 @@ export interface Address {
label?: string;
}
export interface LuckItem {
- percent: number /* float64 */;
+ percent?: number /* float64 */;
expected_timestamp: number /* uint64 */;
average_interval_seconds: number /* uint64 */;
}
diff --git a/frontend/types/api/mobile.ts b/frontend/types/api/mobile.ts
index e4837d1fdb..2bd2184b4c 100644
--- a/frontend/types/api/mobile.ts
+++ b/frontend/types/api/mobile.ts
@@ -14,11 +14,11 @@ export interface MobileWidgetData {
validator_state_counts: ValidatorStateCounts;
last_24h_income: ClElValue;
last_7d_income: ClElValue;
- last_30d_apr: number /* float64 */;
- last_30d_efficiency: number /* float64 */;
- network_efficiency: number /* float64 */;
+ last_30d_apr?: number /* float64 */;
+ last_30d_efficiency?: number /* float64 */;
+ network_efficiency?: number /* float64 */;
rpl_price: string /* decimal.Decimal */;
- rpl_apr: number /* float64 */;
+ rpl_apr?: number /* float64 */;
el_cl_price: number /* float64 */;
}
export type InternalGetValidatorDashboardMobileWidgetResponse = ApiDataResponse;
diff --git a/frontend/types/api/validator_dashboard.ts b/frontend/types/api/validator_dashboard.ts
index 7e8eea3964..7dd061b8f8 100644
--- a/frontend/types/api/validator_dashboard.ts
+++ b/frontend/types/api/validator_dashboard.ts
@@ -21,9 +21,9 @@ export interface VDBOverviewData {
network: number /* uint64 */;
groups: VDBOverviewGroup[];
validators: ValidatorStateCounts;
- efficiency: PeriodicValues;
+ efficiency: PeriodicValues;
rewards: PeriodicValues>;
- apr: PeriodicValues>;
+ apr: PeriodicValues>;
chart_history_seconds: ChartHistorySeconds;
balances: ValidatorBalances;
is_above_effective_balance_limit: boolean; // refers to owner; relevant for shared dashboards
@@ -47,7 +47,7 @@ export interface VDBSummaryTableRow {
group_id: number /* int64 */;
status: VDBSummaryStatus;
validators: VDBSummaryValidators;
- efficiency: number /* float64 */;
+ efficiency?: number /* float64 */;
average_network_efficiency: number /* float64 */;
attestations: StatusCount;
proposals: StatusCount;
@@ -70,23 +70,23 @@ export interface VDBGroupSummaryMissedRewards {
sync: string /* decimal.Decimal */;
}
export interface VDBGroupSummaryData {
- efficiency: number /* float64 */;
+ efficiency?: number /* float64 */;
balances: ValidatorBalances;
rewards: ClElValue;
attestations_head: StatusCount;
attestations_source: StatusCount;
attestations_target: StatusCount;
- attestation_efficiency: number /* float64 */;
+ attestation_efficiency?: number /* float64 */;
attestation_avg_incl_dist: number /* float64 */;
sync: VDBGroupSummaryColumnItem;
sync_count: VDBGroupSummarySyncCount;
- sync_efficiency: number /* float64 */;
+ sync_efficiency?: number /* float64 */;
slashings: VDBGroupSummaryColumnItem; // Failed slashings are count of validators in the group that were slashed
proposal_validators: number /* uint64 */[]; // fill with up to 3 validator indexes
proposal_validator_count: number /* uint64 */; // number of distinct validators
- proposal_efficiency: number /* float64 */;
+ proposal_efficiency?: number /* float64 */;
missed_rewards: VDBGroupSummaryMissedRewards;
- apr: ClElValue;
+ apr: ClElValue;
luck: Luck;
rocket_pool?: {
minipools: number /* uint64 */;