diff --git a/backend/pkg/api/data_access/dummy.go b/backend/pkg/api/data_access/dummy.go index 596242c40..0de2a3f3a 100644 --- a/backend/pkg/api/data_access/dummy.go +++ b/backend/pkg/api/data_access/dummy.go @@ -278,7 +278,7 @@ func (d *DummyService) AddValidatorDashboardValidatorsByGraffiti(ctx context.Con return getDummyData[[]t.VDBPostValidatorsData](ctx) } -func (d *DummyService) GetValidatorDashboardValidators(ctx context.Context, dashboardId t.VDBId, groupId int64, cursor string, colSort t.Sort[enums.VDBManageValidatorsColumn], search t.VDBManageValidatorsSearch, limit uint64) ([]t.VDBManageValidatorsTableRow, *t.Paging, error) { +func (d *DummyService) GetValidatorDashboardValidators(ctx context.Context, dashboardId t.VDBId, groupId int64, cursor t.ValidatorsCursor, colSort t.Sort[enums.VDBManageValidatorsColumn], search t.VDBManageValidatorsSearch, limit uint64) ([]t.VDBManageValidatorsTableRow, *t.Paging, error) { return getDummyWithPaging[t.VDBManageValidatorsTableRow](ctx) } @@ -334,7 +334,7 @@ func (d *DummyService) GetValidatorDashboardProposalSummaryValidators(ctx contex return getDummyStruct[t.VDBProposalSummaryValidators](ctx) } -func (d *DummyService) GetValidatorDashboardRewards(ctx context.Context, dashboardId t.VDBId, cursor string, colSort t.Sort[enums.VDBRewardsColumn], search string, limit uint64, protocolModes t.VDBProtocolModes) ([]t.VDBRewardsTableRow, *t.Paging, error) { +func (d *DummyService) GetValidatorDashboardRewards(ctx context.Context, dashboardId t.VDBId, cursor t.RewardsCursor, colSort t.Sort[enums.VDBRewardsColumn], search string, limit uint64, protocolModes t.VDBProtocolModes) ([]t.VDBRewardsTableRow, *t.Paging, error) { return getDummyWithPaging[t.VDBRewardsTableRow](ctx) } @@ -346,11 +346,11 @@ func (d *DummyService) GetValidatorDashboardRewardsChart(ctx context.Context, da return getDummyStruct[t.ChartData[int, decimal.Decimal]](ctx) } -func (d *DummyService) GetValidatorDashboardDuties(ctx context.Context, dashboardId t.VDBId, epoch uint64, groupId int64, cursor string, colSort t.Sort[enums.VDBDutiesColumn], search string, limit uint64, protocolModes t.VDBProtocolModes) ([]t.VDBEpochDutiesTableRow, *t.Paging, error) { +func (d *DummyService) GetValidatorDashboardDuties(ctx context.Context, dashboardId t.VDBId, epoch uint64, groupId int64, cursor t.ValidatorDutiesCursor, colSort t.Sort[enums.VDBDutiesColumn], search string, limit uint64, protocolModes t.VDBProtocolModes) ([]t.VDBEpochDutiesTableRow, *t.Paging, error) { return getDummyWithPaging[t.VDBEpochDutiesTableRow](ctx) } -func (d *DummyService) GetValidatorDashboardBlocks(ctx context.Context, dashboardId t.VDBId, cursor string, colSort t.Sort[enums.VDBBlocksColumn], search t.VDBBlocksSearch, limit uint64, protocolModes t.VDBProtocolModes) ([]t.VDBBlocksTableRow, *t.Paging, error) { +func (d *DummyService) GetValidatorDashboardBlocks(ctx context.Context, dashboardId t.VDBId, cursor t.BlocksCursor, colSort t.Sort[enums.VDBBlocksColumn], search t.VDBBlocksSearch, limit uint64, protocolModes t.VDBProtocolModes) ([]t.VDBBlocksTableRow, *t.Paging, error) { return getDummyWithPaging[t.VDBBlocksTableRow](ctx) } @@ -362,11 +362,11 @@ func (d *DummyService) GetValidatorDashboardGroupHeatmap(ctx context.Context, da return getDummyStruct[t.VDBHeatmapTooltipData](ctx) } -func (d *DummyService) GetValidatorDashboardElDeposits(ctx context.Context, dashboardId t.VDBId, cursor string, limit uint64) ([]t.VDBExecutionDepositsTableRow, *t.Paging, error) { +func (d *DummyService) GetValidatorDashboardElDeposits(ctx context.Context, dashboardId t.VDBId, cursor t.ELDepositsCursor, limit uint64) ([]t.VDBExecutionDepositsTableRow, *t.Paging, error) { return getDummyWithPaging[t.VDBExecutionDepositsTableRow](ctx) } -func (d *DummyService) GetValidatorDashboardClDeposits(ctx context.Context, dashboardId t.VDBId, cursor string, limit uint64) ([]t.VDBConsensusDepositsTableRow, *t.Paging, error) { +func (d *DummyService) GetValidatorDashboardClDeposits(ctx context.Context, dashboardId t.VDBId, cursor t.CLDepositsCursor, limit uint64) ([]t.VDBConsensusDepositsTableRow, *t.Paging, error) { return getDummyWithPaging[t.VDBConsensusDepositsTableRow](ctx) } @@ -378,7 +378,7 @@ func (d *DummyService) GetValidatorDashboardTotalClDeposits(ctx context.Context, return getDummyStruct[t.VDBTotalConsensusDepositsData](ctx) } -func (d *DummyService) GetValidatorDashboardWithdrawals(ctx context.Context, dashboardId t.VDBId, cursor string, colSort t.Sort[enums.VDBWithdrawalsColumn], search string, limit uint64, protocolModes t.VDBProtocolModes) ([]t.VDBWithdrawalsTableRow, *t.Paging, error) { +func (d *DummyService) GetValidatorDashboardWithdrawals(ctx context.Context, dashboardId t.VDBId, cursor t.WithdrawalsCursor, colSort t.Sort[enums.VDBWithdrawalsColumn], search string, limit uint64, protocolModes t.VDBProtocolModes) ([]t.VDBWithdrawalsTableRow, *t.Paging, error) { return []t.VDBWithdrawalsTableRow{}, &t.Paging{}, nil } @@ -386,7 +386,7 @@ func (d *DummyService) GetValidatorDashboardTotalWithdrawals(ctx context.Context return getDummyStruct[t.VDBTotalWithdrawalsData](ctx) } -func (d *DummyService) GetValidatorDashboardRocketPool(ctx context.Context, dashboardId t.VDBId, cursor string, colSort t.Sort[enums.VDBRocketPoolColumn], search string, limit uint64) ([]t.VDBRocketPoolTableRow, *t.Paging, error) { +func (d *DummyService) GetValidatorDashboardRocketPool(ctx context.Context, dashboardId t.VDBId, cursor t.VDBRocketPoolCursor, colSort t.Sort[enums.VDBRocketPoolColumn], search string, limit uint64) ([]t.VDBRocketPoolTableRow, *t.Paging, error) { return getDummyWithPaging[t.VDBRocketPoolTableRow](ctx) } @@ -394,7 +394,7 @@ func (d *DummyService) GetValidatorDashboardTotalRocketPool(ctx context.Context, return getDummyStruct[t.VDBRocketPoolTableRow](ctx) } -func (d *DummyService) GetValidatorDashboardRocketPoolMinipools(ctx context.Context, dashboardId t.VDBId, node string, cursor string, colSort t.Sort[enums.VDBRocketPoolMinipoolsColumn], search string, limit uint64) ([]t.VDBRocketPoolMinipoolsTableRow, *t.Paging, error) { +func (d *DummyService) GetValidatorDashboardRocketPoolMinipools(ctx context.Context, dashboardId t.VDBId, node string, cursor t.VDBRocketPoolMinipoolsCursor, colSort t.Sort[enums.VDBRocketPoolMinipoolsColumn], search string, limit uint64) ([]t.VDBRocketPoolMinipoolsTableRow, *t.Paging, error) { return getDummyWithPaging[t.VDBRocketPoolMinipoolsTableRow](ctx) } @@ -545,7 +545,7 @@ func (d *DummyService) GetValidatorDashboardPublicIdCount(ctx context.Context, d func (d *DummyService) GetNotificationOverview(ctx context.Context, userId uint64) (*t.NotificationOverviewData, error) { return getDummyStruct[t.NotificationOverviewData](ctx) } -func (d *DummyService) GetDashboardNotifications(ctx context.Context, userId uint64, chainIds []uint64, cursor string, colSort t.Sort[enums.NotificationDashboardsColumn], search string, limit uint64) ([]t.NotificationDashboardsTableRow, *t.Paging, error) { +func (d *DummyService) GetDashboardNotifications(ctx context.Context, userId uint64, chainIds []uint64, cursor t.NotificationsDashboardsCursor, colSort t.Sort[enums.NotificationDashboardsColumn], search string, limit uint64) ([]t.NotificationDashboardsTableRow, *t.Paging, error) { return getDummyWithPaging[t.NotificationDashboardsTableRow](ctx) } @@ -557,16 +557,16 @@ func (d *DummyService) GetAccountDashboardNotificationDetails(ctx context.Contex return getDummyStruct[t.NotificationAccountDashboardDetail](ctx) } -func (d *DummyService) GetMachineNotifications(ctx context.Context, userId uint64, cursor string, colSort t.Sort[enums.NotificationMachinesColumn], search string, limit uint64) ([]t.NotificationMachinesTableRow, *t.Paging, error) { +func (d *DummyService) GetMachineNotifications(ctx context.Context, userId uint64, cursor t.NotificationMachinesCursor, colSort t.Sort[enums.NotificationMachinesColumn], search string, limit uint64) ([]t.NotificationMachinesTableRow, *t.Paging, error) { return getDummyWithPaging[t.NotificationMachinesTableRow](ctx) } -func (d *DummyService) GetClientNotifications(ctx context.Context, userId uint64, cursor string, colSort t.Sort[enums.NotificationClientsColumn], search string, limit uint64) ([]t.NotificationClientsTableRow, *t.Paging, error) { +func (d *DummyService) GetClientNotifications(ctx context.Context, userId uint64, cursor t.NotificationClientsCursor, colSort t.Sort[enums.NotificationClientsColumn], search string, limit uint64) ([]t.NotificationClientsTableRow, *t.Paging, error) { return getDummyWithPaging[t.NotificationClientsTableRow](ctx) } -func (d *DummyService) GetRocketPoolNotifications(ctx context.Context, userId uint64, cursor string, colSort t.Sort[enums.NotificationRocketPoolColumn], search string, limit uint64) ([]t.NotificationRocketPoolTableRow, *t.Paging, error) { +func (d *DummyService) GetRocketPoolNotifications(ctx context.Context, userId uint64, cursor t.NotificationRocketPoolsCursor, colSort t.Sort[enums.NotificationRocketPoolColumn], search string, limit uint64) ([]t.NotificationRocketPoolTableRow, *t.Paging, error) { return getDummyWithPaging[t.NotificationRocketPoolTableRow](ctx) } -func (d *DummyService) GetNetworkNotifications(ctx context.Context, userId uint64, cursor string, colSort t.Sort[enums.NotificationNetworksColumn], limit uint64) ([]t.NotificationNetworksTableRow, *t.Paging, error) { +func (d *DummyService) GetNetworkNotifications(ctx context.Context, userId uint64, cursor t.NotificationNetworksCursor, colSort t.Sort[enums.NotificationNetworksColumn], limit uint64) ([]t.NotificationNetworksTableRow, *t.Paging, error) { return getDummyWithPaging[t.NotificationNetworksTableRow](ctx) } @@ -593,7 +593,7 @@ func (d *DummyService) UpdateNotificationSettingsClients(ctx context.Context, us return getDummyStruct[t.NotificationSettingsClient](ctx) } -func (d *DummyService) GetNotificationSettingsDashboards(ctx context.Context, userId uint64, cursor string, colSort t.Sort[enums.NotificationSettingsDashboardColumn], search string, limit uint64) ([]t.NotificationSettingsDashboardsTableRow, *t.Paging, error) { +func (d *DummyService) GetNotificationSettingsDashboards(ctx context.Context, userId uint64, cursor t.NotificationSettingsCursor, colSort t.Sort[enums.NotificationSettingsDashboardColumn], search string, limit uint64) ([]t.NotificationSettingsDashboardsTableRow, *t.Paging, error) { r, p, err := getDummyWithPaging[t.NotificationSettingsDashboardsTableRow](ctx) for i, n := range r { var settings interface{} @@ -783,7 +783,7 @@ func (d *DummyService) PostUserMachineMetrics(ctx context.Context, userID uint64 return nil } -func (d *DummyService) GetValidatorDashboardMobileValidators(ctx context.Context, dashboardId t.VDBId, period enums.TimePeriod, cursor string, colSort t.Sort[enums.VDBMobileValidatorsColumn], search string, limit uint64) ([]t.MobileValidatorDashboardValidatorsTableRow, *t.Paging, error) { +func (d *DummyService) GetValidatorDashboardMobileValidators(ctx context.Context, dashboardId t.VDBId, period enums.TimePeriod, cursor t.VDBMobileValidatorsCursor, colSort t.Sort[enums.VDBMobileValidatorsColumn], search string, limit uint64) ([]t.MobileValidatorDashboardValidatorsTableRow, *t.Paging, error) { return getDummyWithPaging[t.MobileValidatorDashboardValidatorsTableRow](ctx) } diff --git a/backend/pkg/api/data_access/mobile.go b/backend/pkg/api/data_access/mobile.go index 373688439..1e9f45443 100644 --- a/backend/pkg/api/data_access/mobile.go +++ b/backend/pkg/api/data_access/mobile.go @@ -27,7 +27,7 @@ type AppRepository interface { AddMobilePurchase(ctx context.Context, tx *sql.Tx, userID uint64, paymentDetails t.MobileSubscription, verifyResponse *userservice.VerifyResponse, extSubscriptionId string) error GetLatestBundleForNativeVersion(ctx context.Context, nativeVersion uint64) (*t.MobileAppBundleStats, error) IncrementBundleDeliveryCount(ctx context.Context, bundleVerison uint64) error - GetValidatorDashboardMobileValidators(ctx context.Context, dashboardId t.VDBId, period enums.TimePeriod, cursor string, colSort t.Sort[enums.VDBMobileValidatorsColumn], search string, limit uint64) ([]t.MobileValidatorDashboardValidatorsTableRow, *t.Paging, error) + GetValidatorDashboardMobileValidators(ctx context.Context, dashboardId t.VDBId, period enums.TimePeriod, cursor t.VDBMobileValidatorsCursor, colSort t.Sort[enums.VDBMobileValidatorsColumn], search string, limit uint64) ([]t.MobileValidatorDashboardValidatorsTableRow, *t.Paging, error) } // GetUserIdByRefreshToken basically used to confirm the claimed user id with the refresh token. Returns the userId if successful @@ -363,6 +363,6 @@ func (d *DataAccessService) getInternalRpNetworkStats(ctx context.Context) (*t.R return &networkStats, err } -func (d *DataAccessService) GetValidatorDashboardMobileValidators(ctx context.Context, dashboardId t.VDBId, period enums.TimePeriod, cursor string, colSort t.Sort[enums.VDBMobileValidatorsColumn], search string, limit uint64) ([]t.MobileValidatorDashboardValidatorsTableRow, *t.Paging, error) { +func (d *DataAccessService) GetValidatorDashboardMobileValidators(ctx context.Context, dashboardId t.VDBId, period enums.TimePeriod, cursor t.VDBMobileValidatorsCursor, colSort t.Sort[enums.VDBMobileValidatorsColumn], search string, limit uint64) ([]t.MobileValidatorDashboardValidatorsTableRow, *t.Paging, error) { return d.dummy.GetValidatorDashboardMobileValidators(ctx, dashboardId, period, cursor, colSort, search, limit) } diff --git a/backend/pkg/api/data_access/notifications.go b/backend/pkg/api/data_access/notifications.go index 4774fed0c..759508ab4 100644 --- a/backend/pkg/api/data_access/notifications.go +++ b/backend/pkg/api/data_access/notifications.go @@ -37,15 +37,15 @@ import ( type NotificationsRepository interface { GetNotificationOverview(ctx context.Context, userId uint64) (*t.NotificationOverviewData, error) - GetDashboardNotifications(ctx context.Context, userId uint64, chainIds []uint64, cursor string, colSort t.Sort[enums.NotificationDashboardsColumn], search string, limit uint64) ([]t.NotificationDashboardsTableRow, *t.Paging, error) + GetDashboardNotifications(ctx context.Context, userId uint64, chainIds []uint64, cursor t.NotificationsDashboardsCursor, colSort t.Sort[enums.NotificationDashboardsColumn], search string, limit uint64) ([]t.NotificationDashboardsTableRow, *t.Paging, error) // depending on how notifications are implemented, we may need to use something other than `notificationId` for identifying the notification GetValidatorDashboardNotificationDetails(ctx context.Context, dashboardId t.VDBIdPrimary, groupId uint64, epoch uint64, search string) (*t.NotificationValidatorDashboardDetail, error) GetAccountDashboardNotificationDetails(ctx context.Context, dashboardId uint64, groupId uint64, epoch uint64, search string) (*t.NotificationAccountDashboardDetail, error) - GetMachineNotifications(ctx context.Context, userId uint64, cursor string, colSort t.Sort[enums.NotificationMachinesColumn], search string, limit uint64) ([]t.NotificationMachinesTableRow, *t.Paging, error) - GetClientNotifications(ctx context.Context, userId uint64, cursor string, colSort t.Sort[enums.NotificationClientsColumn], search string, limit uint64) ([]t.NotificationClientsTableRow, *t.Paging, error) - GetRocketPoolNotifications(ctx context.Context, userId uint64, cursor string, colSort t.Sort[enums.NotificationRocketPoolColumn], search string, limit uint64) ([]t.NotificationRocketPoolTableRow, *t.Paging, error) - GetNetworkNotifications(ctx context.Context, userId uint64, cursor string, colSort t.Sort[enums.NotificationNetworksColumn], limit uint64) ([]t.NotificationNetworksTableRow, *t.Paging, error) + GetMachineNotifications(ctx context.Context, userId uint64, cursor t.NotificationMachinesCursor, colSort t.Sort[enums.NotificationMachinesColumn], search string, limit uint64) ([]t.NotificationMachinesTableRow, *t.Paging, error) + GetClientNotifications(ctx context.Context, userId uint64, cursor t.NotificationClientsCursor, colSort t.Sort[enums.NotificationClientsColumn], search string, limit uint64) ([]t.NotificationClientsTableRow, *t.Paging, error) + GetRocketPoolNotifications(ctx context.Context, userId uint64, cursor t.NotificationRocketPoolsCursor, colSort t.Sort[enums.NotificationRocketPoolColumn], search string, limit uint64) ([]t.NotificationRocketPoolTableRow, *t.Paging, error) + GetNetworkNotifications(ctx context.Context, userId uint64, cursor t.NotificationNetworksCursor, colSort t.Sort[enums.NotificationNetworksColumn], limit uint64) ([]t.NotificationNetworksTableRow, *t.Paging, error) GetNotificationSettings(ctx context.Context, userId uint64) (*t.NotificationSettings, error) GetNotificationSettingsDefaultValues(ctx context.Context) (*t.NotificationSettingsDefaultValues, error) @@ -55,7 +55,7 @@ type NotificationsRepository interface { UpdateNotificationSettingsPairedDevice(ctx context.Context, pairedDeviceId uint64, name string, IsNotificationsEnabled bool) error DeleteNotificationSettingsPairedDevice(ctx context.Context, pairedDeviceId uint64) error UpdateNotificationSettingsClients(ctx context.Context, userId uint64, clientId uint64, IsSubscribed bool) (*t.NotificationSettingsClient, error) - GetNotificationSettingsDashboards(ctx context.Context, userId uint64, cursor string, colSort t.Sort[enums.NotificationSettingsDashboardColumn], search string, limit uint64) ([]t.NotificationSettingsDashboardsTableRow, *t.Paging, error) + GetNotificationSettingsDashboards(ctx context.Context, userId uint64, cursor t.NotificationSettingsCursor, colSort t.Sort[enums.NotificationSettingsDashboardColumn], search string, limit uint64) ([]t.NotificationSettingsDashboardsTableRow, *t.Paging, error) UpdateNotificationSettingsValidatorDashboard(ctx context.Context, userId uint64, dashboardId t.VDBIdPrimary, groupId uint64, settings t.NotificationSettingsValidatorDashboard) error UpdateNotificationSettingsAccountDashboard(ctx context.Context, userId uint64, dashboardId t.VDBIdPrimary, groupId uint64, settings t.NotificationSettingsAccountDashboard) error @@ -258,16 +258,8 @@ func (d *DataAccessService) GetNotificationOverview(ctx context.Context, userId return &response, err } -func (d *DataAccessService) GetDashboardNotifications(ctx context.Context, userId uint64, chainIds []uint64, cursor string, colSort t.Sort[enums.NotificationDashboardsColumn], search string, limit uint64) ([]t.NotificationDashboardsTableRow, *t.Paging, error) { +func (d *DataAccessService) GetDashboardNotifications(ctx context.Context, userId uint64, chainIds []uint64, cursor t.NotificationsDashboardsCursor, colSort t.Sort[enums.NotificationDashboardsColumn], search string, limit uint64) ([]t.NotificationDashboardsTableRow, *t.Paging, error) { response := []t.NotificationDashboardsTableRow{} - var err error - - var currentCursor t.NotificationsDashboardsCursor - if cursor != "" { - if currentCursor, err = utils.StringToCursor[t.NotificationsDashboardsCursor](cursor); err != nil { - return nil, nil, fmt.Errorf("failed to parse passed cursor as NotificationsDashboardsCursor: %w", err) - } - } // validator query vdbQuery := goqu.Dialect("postgres"). @@ -344,14 +336,14 @@ func (d *DataAccessService) GetDashboardNotifications(ctx context.Context, userI // sorting defaultColumns := []t.SortColumn{ - {Column: enums.NotificationsDashboardsColumns.Timestamp.ToExpr(), Desc: true, Offset: currentCursor.Epoch}, - {Column: enums.NotificationsDashboardsColumns.DashboardName.ToExpr(), Desc: false, Offset: currentCursor.DashboardName}, - {Column: enums.NotificationsDashboardsColumns.DashboardId.ToExpr(), Desc: false, Offset: currentCursor.DashboardId}, - {Column: enums.NotificationsDashboardsColumns.GroupName.ToExpr(), Desc: false, Offset: currentCursor.GroupName}, - {Column: enums.NotificationsDashboardsColumns.GroupId.ToExpr(), Desc: false, Offset: currentCursor.GroupId}, - {Column: enums.NotificationsDashboardsColumns.ChainId.ToExpr(), Desc: true, Offset: currentCursor.ChainId}, - } - order, directions := applySortAndPagination(defaultColumns, t.SortColumn{Column: colSort.Column.ToExpr(), Desc: colSort.Desc}, currentCursor.GenericCursor) + {Column: enums.NotificationsDashboardsColumns.Timestamp.ToExpr(), Desc: true, Offset: cursor.Epoch}, + {Column: enums.NotificationsDashboardsColumns.DashboardName.ToExpr(), Desc: false, Offset: cursor.DashboardName}, + {Column: enums.NotificationsDashboardsColumns.DashboardId.ToExpr(), Desc: false, Offset: cursor.DashboardId}, + {Column: enums.NotificationsDashboardsColumns.GroupName.ToExpr(), Desc: false, Offset: cursor.GroupName}, + {Column: enums.NotificationsDashboardsColumns.GroupId.ToExpr(), Desc: false, Offset: cursor.GroupId}, + {Column: enums.NotificationsDashboardsColumns.ChainId.ToExpr(), Desc: true, Offset: cursor.ChainId}, + } + order, directions := applySortAndPagination(defaultColumns, t.SortColumn{Column: colSort.Column.ToExpr(), Desc: colSort.Desc}, cursor.GenericCursor) unionQuery = unionQuery.Order(order...) if directions != nil { unionQuery = unionQuery.Where(directions) @@ -382,14 +374,14 @@ func (d *DataAccessService) GetDashboardNotifications(ctx context.Context, userI if moreDataFlag { response = response[:len(response)-1] } - if currentCursor.IsReverse() { + if cursor.IsReverse() { slices.Reverse(response) } - if !moreDataFlag && !currentCursor.IsValid() { + if !moreDataFlag && !cursor.IsValid() { // No paging required return response, &t.Paging{}, nil } - paging, err := utils.GetPagingFromData(response, currentCursor, moreDataFlag) + paging, err := utils.GetPagingFromData(response, cursor, moreDataFlag) if err != nil { return nil, nil, err } @@ -684,20 +676,10 @@ func (d *DataAccessService) GetAccountDashboardNotificationDetails(ctx context.C return d.dummy.GetAccountDashboardNotificationDetails(ctx, dashboardId, groupId, epoch, search) } -func (d *DataAccessService) GetMachineNotifications(ctx context.Context, userId uint64, cursor string, colSort t.Sort[enums.NotificationMachinesColumn], search string, limit uint64) ([]t.NotificationMachinesTableRow, *t.Paging, error) { +func (d *DataAccessService) GetMachineNotifications(ctx context.Context, userId uint64, cursor t.NotificationMachinesCursor, colSort t.Sort[enums.NotificationMachinesColumn], search string, limit uint64) ([]t.NotificationMachinesTableRow, *t.Paging, error) { result := make([]t.NotificationMachinesTableRow, 0) var paging t.Paging - // Initialize the cursor - var currentCursor t.NotificationMachinesCursor - var err error - if cursor != "" { - currentCursor, err = utils.StringToCursor[t.NotificationMachinesCursor](cursor) - if err != nil { - return nil, nil, fmt.Errorf("failed to parse passed cursor as NotificationMachinesCursor: %w", err) - } - } - // ------------------------------------- // Get the machine notification history notificationHistory := []struct { @@ -726,19 +708,19 @@ func (d *DataAccessService) GetMachineNotifications(ctx context.Context, userId // Sorting and limiting if cursor is present defaultColumns := []t.SortColumn{ - {Column: enums.NotificationsMachinesColumns.Timestamp.ToExpr(), Desc: true, Offset: currentCursor.Epoch}, - {Column: enums.NotificationsMachinesColumns.MachineId.ToExpr(), Desc: false, Offset: currentCursor.MachineId}, - {Column: enums.NotificationsMachinesColumns.EventType.ToExpr(), Desc: false, Offset: currentCursor.EventType}, + {Column: enums.NotificationsMachinesColumns.Timestamp.ToExpr(), Desc: true, Offset: cursor.Epoch}, + {Column: enums.NotificationsMachinesColumns.MachineId.ToExpr(), Desc: false, Offset: cursor.MachineId}, + {Column: enums.NotificationsMachinesColumns.EventType.ToExpr(), Desc: false, Offset: cursor.EventType}, } var offset interface{} switch colSort.Column { case enums.NotificationsMachinesColumns.MachineName: - offset = currentCursor.MachineName + offset = cursor.MachineName case enums.NotificationsMachinesColumns.Threshold: - offset = currentCursor.EventThreshold + offset = cursor.EventThreshold } - order, directions := applySortAndPagination(defaultColumns, t.SortColumn{Column: colSort.Column.ToExpr(), Desc: colSort.Desc, Offset: offset}, currentCursor.GenericCursor) + order, directions := applySortAndPagination(defaultColumns, t.SortColumn{Column: colSort.Column.ToExpr(), Desc: colSort.Desc, Offset: offset}, cursor.GenericCursor) ds = ds.Order(order...) if directions != nil { ds = ds.Where(directions) @@ -783,7 +765,7 @@ func (d *DataAccessService) GetMachineNotifications(ctx context.Context, userId // Flag if above limit moreDataFlag := len(result) > int(limit) - if !moreDataFlag && !currentCursor.IsValid() { + if !moreDataFlag && !cursor.IsValid() { // No paging required return result, &paging, nil } @@ -794,32 +776,22 @@ func (d *DataAccessService) GetMachineNotifications(ctx context.Context, userId cursorData = cursorData[:limit] } - if currentCursor.IsReverse() { + if cursor.IsReverse() { slices.Reverse(result) slices.Reverse(cursorData) } - p, err := utils.GetPagingFromData(cursorData, currentCursor, moreDataFlag) + p, err := utils.GetPagingFromData(cursorData, cursor, moreDataFlag) if err != nil { return nil, nil, fmt.Errorf("failed to get paging: %w", err) } return result, p, nil } -func (d *DataAccessService) GetClientNotifications(ctx context.Context, userId uint64, cursor string, colSort t.Sort[enums.NotificationClientsColumn], search string, limit uint64) ([]t.NotificationClientsTableRow, *t.Paging, error) { +func (d *DataAccessService) GetClientNotifications(ctx context.Context, userId uint64, cursor t.NotificationClientsCursor, colSort t.Sort[enums.NotificationClientsColumn], search string, limit uint64) ([]t.NotificationClientsTableRow, *t.Paging, error) { result := make([]t.NotificationClientsTableRow, 0) var paging t.Paging - // Initialize the cursor - var currentCursor t.NotificationClientsCursor - var err error - if cursor != "" { - currentCursor, err = utils.StringToCursor[t.NotificationClientsCursor](cursor) - if err != nil { - return nil, nil, fmt.Errorf("failed to parse passed cursor as NotificationClientsCursor: %w", err) - } - } - // ------------------------------------- // Get the client notification history notificationHistory := []struct { @@ -847,10 +819,10 @@ func (d *DataAccessService) GetClientNotifications(ctx context.Context, userId u // Sorting and limiting if cursor is present // Rows can be uniquely identified by (epoch, client) defaultColumns := []t.SortColumn{ - {Column: enums.NotificationsClientsColumns.Timestamp.ToExpr(), Desc: true, Offset: currentCursor.Epoch}, - {Column: enums.NotificationsClientsColumns.ClientName.ToExpr(), Desc: false, Offset: currentCursor.Client}, + {Column: enums.NotificationsClientsColumns.Timestamp.ToExpr(), Desc: true, Offset: cursor.Epoch}, + {Column: enums.NotificationsClientsColumns.ClientName.ToExpr(), Desc: false, Offset: cursor.Client}, } - order, directions := applySortAndPagination(defaultColumns, t.SortColumn{Column: colSort.Column.ToExpr(), Desc: colSort.Desc}, currentCursor.GenericCursor) + order, directions := applySortAndPagination(defaultColumns, t.SortColumn{Column: colSort.Column.ToExpr(), Desc: colSort.Desc}, cursor.GenericCursor) ds = ds.Order(order...) if directions != nil { ds = ds.Where(directions) @@ -884,7 +856,7 @@ func (d *DataAccessService) GetClientNotifications(ctx context.Context, userId u // Flag if above limit moreDataFlag := len(result) > int(limit) - if !moreDataFlag && !currentCursor.IsValid() { + if !moreDataFlag && !cursor.IsValid() { // No paging required return result, &paging, nil } @@ -895,19 +867,19 @@ func (d *DataAccessService) GetClientNotifications(ctx context.Context, userId u cursorData = cursorData[:limit] } - if currentCursor.IsReverse() { + if cursor.IsReverse() { slices.Reverse(result) slices.Reverse(cursorData) } - p, err := utils.GetPagingFromData(cursorData, currentCursor, moreDataFlag) + p, err := utils.GetPagingFromData(cursorData, cursor, moreDataFlag) if err != nil { return nil, nil, fmt.Errorf("failed to get paging: %w", err) } return result, p, nil } -func (d *DataAccessService) GetRocketPoolNotifications(ctx context.Context, userId uint64, cursor string, colSort t.Sort[enums.NotificationRocketPoolColumn], search string, limit uint64) ([]t.NotificationRocketPoolTableRow, *t.Paging, error) { +func (d *DataAccessService) GetRocketPoolNotifications(ctx context.Context, userId uint64, cursor t.NotificationRocketPoolsCursor, colSort t.Sort[enums.NotificationRocketPoolColumn], search string, limit uint64) ([]t.NotificationRocketPoolTableRow, *t.Paging, error) { return d.dummy.GetRocketPoolNotifications(ctx, userId, cursor, colSort, search, limit) // TODO: Adjust after db structure has been clarified @@ -1102,20 +1074,10 @@ func (d *DataAccessService) GetRocketPoolNotifications(ctx context.Context, user // return result, p, nil } -func (d *DataAccessService) GetNetworkNotifications(ctx context.Context, userId uint64, cursor string, colSort t.Sort[enums.NotificationNetworksColumn], limit uint64) ([]t.NotificationNetworksTableRow, *t.Paging, error) { +func (d *DataAccessService) GetNetworkNotifications(ctx context.Context, userId uint64, cursor t.NotificationNetworksCursor, colSort t.Sort[enums.NotificationNetworksColumn], limit uint64) ([]t.NotificationNetworksTableRow, *t.Paging, error) { result := make([]t.NotificationNetworksTableRow, 0) var paging t.Paging - // Initialize the cursor - var currentCursor t.NotificationNetworksCursor - var err error - if cursor != "" { - currentCursor, err = utils.StringToCursor[t.NotificationNetworksCursor](cursor) - if err != nil { - return nil, nil, fmt.Errorf("failed to parse passed cursor as NotificationNetworksCursor: %w", err) - } - } - // ------------------------------------- // Get the network notification history notificationHistory := []struct { @@ -1138,11 +1100,11 @@ func (d *DataAccessService) GetNetworkNotifications(ctx context.Context, userId // Sorting and limiting if cursor is present // Rows can be uniquely identified by (epoch, network, event_type) defaultColumns := []t.SortColumn{ - {Column: enums.NotificationNetworksColumns.Timestamp.ToExpr(), Desc: true, Offset: currentCursor.Epoch}, - {Column: enums.NotificationNetworksColumns.Network.ToExpr(), Desc: false, Offset: currentCursor.Network}, - {Column: enums.NotificationNetworksColumns.EventType.ToExpr(), Desc: false, Offset: currentCursor.EventType}, + {Column: enums.NotificationNetworksColumns.Timestamp.ToExpr(), Desc: true, Offset: cursor.Epoch}, + {Column: enums.NotificationNetworksColumns.Network.ToExpr(), Desc: false, Offset: cursor.Network}, + {Column: enums.NotificationNetworksColumns.EventType.ToExpr(), Desc: false, Offset: cursor.EventType}, } - order, directions := applySortAndPagination(defaultColumns, t.SortColumn{Column: colSort.Column.ToExpr(), Desc: colSort.Desc}, currentCursor.GenericCursor) + order, directions := applySortAndPagination(defaultColumns, t.SortColumn{Column: colSort.Column.ToExpr(), Desc: colSort.Desc}, cursor.GenericCursor) ds = ds.Order(order...) if directions != nil { ds = ds.Where(directions) @@ -1189,7 +1151,7 @@ func (d *DataAccessService) GetNetworkNotifications(ctx context.Context, userId // Flag if above limit moreDataFlag := len(result) > int(limit) - if !moreDataFlag && !currentCursor.IsValid() { + if !moreDataFlag && !cursor.IsValid() { // No paging required return result, &paging, nil } @@ -1200,12 +1162,12 @@ func (d *DataAccessService) GetNetworkNotifications(ctx context.Context, userId cursorData = cursorData[:limit] } - if currentCursor.IsReverse() { + if cursor.IsReverse() { slices.Reverse(result) slices.Reverse(cursorData) } - p, err := utils.GetPagingFromData(cursorData, currentCursor, moreDataFlag) + p, err := utils.GetPagingFromData(cursorData, cursor, moreDataFlag) if err != nil { return nil, nil, fmt.Errorf("failed to get paging: %w", err) } @@ -1732,23 +1694,13 @@ func (d *DataAccessService) UpdateNotificationSettingsClients(ctx context.Contex return result, nil } -func (d *DataAccessService) GetNotificationSettingsDashboards(ctx context.Context, userId uint64, cursor string, colSort t.Sort[enums.NotificationSettingsDashboardColumn], search string, limit uint64) ([]t.NotificationSettingsDashboardsTableRow, *t.Paging, error) { +func (d *DataAccessService) GetNotificationSettingsDashboards(ctx context.Context, userId uint64, cursor t.NotificationSettingsCursor, colSort t.Sort[enums.NotificationSettingsDashboardColumn], search string, limit uint64) ([]t.NotificationSettingsDashboardsTableRow, *t.Paging, error) { result := make([]t.NotificationSettingsDashboardsTableRow, 0) var paging t.Paging wg := errgroup.Group{} - // Initialize the cursor - var currentCursor t.NotificationSettingsCursor - var err error - if cursor != "" { - currentCursor, err = utils.StringToCursor[t.NotificationSettingsCursor](cursor) - if err != nil { - return nil, nil, fmt.Errorf("failed to parse passed cursor as NotificationSettingsCursor: %w", err) - } - } - - isReverseDirection := (colSort.Desc && !currentCursor.IsReverse()) || (!colSort.Desc && currentCursor.IsReverse()) + isReverseDirection := (colSort.Desc && !cursor.IsReverse()) || (!colSort.Desc && cursor.IsReverse()) // ------------------------------------- // Get the events @@ -1837,7 +1789,7 @@ func (d *DataAccessService) GetNotificationSettingsDashboards(ctx context.Contex // return nil // }) - err = wg.Wait() + err := wg.Wait() if err != nil { return nil, nil, fmt.Errorf("error retrieving dashboard notification data: %w", err) } @@ -2049,11 +2001,11 @@ func (d *DataAccessService) GetNotificationSettingsDashboards(ctx context.Contex // Paging // Find the index for the cursor and limit the data - if currentCursor.IsValid() { + if cursor.IsValid() { for idx, row := range result { - if row.DashboardId == currentCursor.DashboardId && - row.GroupId == currentCursor.GroupId && - row.IsAccountDashboard == currentCursor.IsAccountDashboard { + if row.DashboardId == cursor.DashboardId && + row.GroupId == cursor.GroupId && + row.IsAccountDashboard == cursor.IsAccountDashboard { result = result[idx+1:] break } @@ -2062,7 +2014,7 @@ func (d *DataAccessService) GetNotificationSettingsDashboards(ctx context.Contex // Flag if above limit moreDataFlag := len(result) > int(limit) - if !moreDataFlag && !currentCursor.IsValid() { + if !moreDataFlag && !cursor.IsValid() { // No paging required return result, &paging, nil } @@ -2072,11 +2024,11 @@ func (d *DataAccessService) GetNotificationSettingsDashboards(ctx context.Contex result = result[:limit] } - if currentCursor.IsReverse() { + if cursor.IsReverse() { slices.Reverse(result) } - p, err := utils.GetPagingFromData(result, currentCursor, moreDataFlag) + p, err := utils.GetPagingFromData(result, cursor, moreDataFlag) if err != nil { return nil, nil, fmt.Errorf("failed to get paging: %w", err) } diff --git a/backend/pkg/api/data_access/vdb.go b/backend/pkg/api/data_access/vdb.go index 3a5cce542..c265e3b21 100644 --- a/backend/pkg/api/data_access/vdb.go +++ b/backend/pkg/api/data_access/vdb.go @@ -34,7 +34,7 @@ type ValidatorDashboardRepository interface { AddValidatorDashboardValidatorsByGraffiti(ctx context.Context, dashboardId t.VDBIdPrimary, groupId uint64, graffiti string, limit uint64) ([]t.VDBPostValidatorsData, error) RemoveValidatorDashboardValidators(ctx context.Context, dashboardId t.VDBIdPrimary, validators []t.VDBValidator) error - GetValidatorDashboardValidators(ctx context.Context, dashboardId t.VDBId, groupId int64, cursor string, colSort t.Sort[enums.VDBManageValidatorsColumn], search t.VDBManageValidatorsSearch, limit uint64) ([]t.VDBManageValidatorsTableRow, *t.Paging, error) + GetValidatorDashboardValidators(ctx context.Context, dashboardId t.VDBId, groupId int64, cursor t.ValidatorsCursor, colSort t.Sort[enums.VDBManageValidatorsColumn], search t.VDBManageValidatorsSearch, limit uint64) ([]t.VDBManageValidatorsTableRow, *t.Paging, error) GetValidatorDashboardValidatorsCount(ctx context.Context, dashboardId t.VDBIdPrimary) (uint64, error) CreateValidatorDashboardPublicId(ctx context.Context, dashboardId t.VDBIdPrimary, name string, shareGroups bool) (*t.VDBPublicId, error) @@ -55,28 +55,28 @@ type ValidatorDashboardRepository interface { GetValidatorDashboardSlashingsSummaryValidators(ctx context.Context, dashboardId t.VDBId, groupId int64, period enums.TimePeriod) (*t.VDBSlashingsSummaryValidators, error) GetValidatorDashboardProposalSummaryValidators(ctx context.Context, dashboardId t.VDBId, groupId int64, period enums.TimePeriod) (*t.VDBProposalSummaryValidators, error) - GetValidatorDashboardRewards(ctx context.Context, dashboardId t.VDBId, cursor string, colSort t.Sort[enums.VDBRewardsColumn], search string, limit uint64, protocolModes t.VDBProtocolModes) ([]t.VDBRewardsTableRow, *t.Paging, error) + GetValidatorDashboardRewards(ctx context.Context, dashboardId t.VDBId, cursor t.RewardsCursor, colSort t.Sort[enums.VDBRewardsColumn], search string, limit uint64, protocolModes t.VDBProtocolModes) ([]t.VDBRewardsTableRow, *t.Paging, error) GetValidatorDashboardGroupRewards(ctx context.Context, dashboardId t.VDBId, groupId int64, epoch uint64, protocolModes t.VDBProtocolModes) (*t.VDBGroupRewardsData, error) GetValidatorDashboardRewardsChart(ctx context.Context, dashboardId t.VDBId, protocolModes t.VDBProtocolModes) (*t.ChartData[int, decimal.Decimal], error) - GetValidatorDashboardDuties(ctx context.Context, dashboardId t.VDBId, epoch uint64, groupId int64, cursor string, colSort t.Sort[enums.VDBDutiesColumn], search string, limit uint64, protocolModes t.VDBProtocolModes) ([]t.VDBEpochDutiesTableRow, *t.Paging, error) + GetValidatorDashboardDuties(ctx context.Context, dashboardId t.VDBId, epoch uint64, groupId int64, cursor t.ValidatorDutiesCursor, colSort t.Sort[enums.VDBDutiesColumn], search string, limit uint64, protocolModes t.VDBProtocolModes) ([]t.VDBEpochDutiesTableRow, *t.Paging, error) - GetValidatorDashboardBlocks(ctx context.Context, dashboardId t.VDBId, cursor string, colSort t.Sort[enums.VDBBlocksColumn], search t.VDBBlocksSearch, limit uint64, protocolModes t.VDBProtocolModes) ([]t.VDBBlocksTableRow, *t.Paging, error) + GetValidatorDashboardBlocks(ctx context.Context, dashboardId t.VDBId, cursor t.BlocksCursor, colSort t.Sort[enums.VDBBlocksColumn], search t.VDBBlocksSearch, limit uint64, protocolModes t.VDBProtocolModes) ([]t.VDBBlocksTableRow, *t.Paging, error) GetValidatorDashboardHeatmap(ctx context.Context, dashboardId t.VDBId, protocolModes t.VDBProtocolModes, aggregation enums.ChartAggregation, afterTs uint64, beforeTs uint64) (*t.VDBHeatmap, error) GetValidatorDashboardGroupHeatmap(ctx context.Context, dashboardId t.VDBId, groupId uint64, protocolModes t.VDBProtocolModes, aggregation enums.ChartAggregation, timestamp uint64) (*t.VDBHeatmapTooltipData, error) - GetValidatorDashboardElDeposits(ctx context.Context, dashboardId t.VDBId, cursor string, limit uint64) ([]t.VDBExecutionDepositsTableRow, *t.Paging, error) - GetValidatorDashboardClDeposits(ctx context.Context, dashboardId t.VDBId, cursor string, limit uint64) ([]t.VDBConsensusDepositsTableRow, *t.Paging, error) + GetValidatorDashboardElDeposits(ctx context.Context, dashboardId t.VDBId, cursor t.ELDepositsCursor, limit uint64) ([]t.VDBExecutionDepositsTableRow, *t.Paging, error) + GetValidatorDashboardClDeposits(ctx context.Context, dashboardId t.VDBId, cursor t.CLDepositsCursor, limit uint64) ([]t.VDBConsensusDepositsTableRow, *t.Paging, error) GetValidatorDashboardTotalElDeposits(ctx context.Context, dashboardId t.VDBId) (*t.VDBTotalExecutionDepositsData, error) GetValidatorDashboardTotalClDeposits(ctx context.Context, dashboardId t.VDBId) (*t.VDBTotalConsensusDepositsData, error) - GetValidatorDashboardWithdrawals(ctx context.Context, dashboardId t.VDBId, cursor string, colSort t.Sort[enums.VDBWithdrawalsColumn], search string, limit uint64, protocolModes t.VDBProtocolModes) ([]t.VDBWithdrawalsTableRow, *t.Paging, error) + GetValidatorDashboardWithdrawals(ctx context.Context, dashboardId t.VDBId, cursor t.WithdrawalsCursor, colSort t.Sort[enums.VDBWithdrawalsColumn], search string, limit uint64, protocolModes t.VDBProtocolModes) ([]t.VDBWithdrawalsTableRow, *t.Paging, error) GetValidatorDashboardTotalWithdrawals(ctx context.Context, dashboardId t.VDBId, search string, protocolModes t.VDBProtocolModes) (*t.VDBTotalWithdrawalsData, error) - GetValidatorDashboardRocketPool(ctx context.Context, dashboardId t.VDBId, cursor string, colSort t.Sort[enums.VDBRocketPoolColumn], search string, limit uint64) ([]t.VDBRocketPoolTableRow, *t.Paging, error) + GetValidatorDashboardRocketPool(ctx context.Context, dashboardId t.VDBId, cursor t.VDBRocketPoolCursor, colSort t.Sort[enums.VDBRocketPoolColumn], search string, limit uint64) ([]t.VDBRocketPoolTableRow, *t.Paging, error) GetValidatorDashboardTotalRocketPool(ctx context.Context, dashboardId t.VDBId, search string) (*t.VDBRocketPoolTableRow, error) - GetValidatorDashboardRocketPoolMinipools(ctx context.Context, dashboardId t.VDBId, node, cursor string, colSort t.Sort[enums.VDBRocketPoolMinipoolsColumn], search string, limit uint64) ([]t.VDBRocketPoolMinipoolsTableRow, *t.Paging, error) + GetValidatorDashboardRocketPoolMinipools(ctx context.Context, dashboardId t.VDBId, node string, cursor t.VDBRocketPoolMinipoolsCursor, colSort t.Sort[enums.VDBRocketPoolMinipoolsColumn], search string, limit uint64) ([]t.VDBRocketPoolMinipoolsTableRow, *t.Paging, error) GetValidatorDashboardMobileWidget(ctx context.Context, dashboardId t.VDBIdPrimary) (*t.MobileWidgetData, error) } diff --git a/backend/pkg/api/data_access/vdb_blocks.go b/backend/pkg/api/data_access/vdb_blocks.go index 032594540..db9cff66a 100644 --- a/backend/pkg/api/data_access/vdb_blocks.go +++ b/backend/pkg/api/data_access/vdb_blocks.go @@ -22,25 +22,17 @@ import ( "github.com/shopspring/decimal" ) -func (d *DataAccessService) GetValidatorDashboardBlocks(ctx context.Context, dashboardId t.VDBId, cursor string, colSort t.Sort[enums.VDBBlocksColumn], search t.VDBBlocksSearch, limit uint64, protocolModes t.VDBProtocolModes) ([]t.VDBBlocksTableRow, *t.Paging, error) { +func (d *DataAccessService) GetValidatorDashboardBlocks(ctx context.Context, dashboardId t.VDBId, cursor t.BlocksCursor, colSort t.Sort[enums.VDBBlocksColumn], search t.VDBBlocksSearch, limit uint64, protocolModes t.VDBProtocolModes) ([]t.VDBBlocksTableRow, *t.Paging, error) { // @DATA-ACCESS incorporate protocolModes // ------------------------------------- // Setup var err error - var currentCursor t.BlocksCursor validatorMapping, err := d.services.GetCurrentValidatorMapping() if err != nil { return nil, nil, err } - // TODO @LuccaBitfly move validation to handler? - if cursor != "" { - if currentCursor, err = utils.StringToCursor[t.BlocksCursor](cursor); err != nil { - return nil, nil, fmt.Errorf("failed to parse passed cursor as BlocksCursor: %w", err) - } - } - validators := goqu.T("validators") // could adapt data type to make handling as table/alias less confusing blocks := goqu.T("blocks") groups := goqu.T("groups") @@ -173,24 +165,24 @@ func (d *DataAccessService) GetValidatorDashboardBlocks(ctx context.Context, das // 3. Sorting and pagination defaultColumns := []t.SortColumn{ - {Column: enums.VDBBlocksColumns.Slot.ToExpr(), Desc: true, Offset: currentCursor.Slot}, + {Column: enums.VDBBlocksColumns.Slot.ToExpr(), Desc: true, Offset: cursor.Slot}, } var offset any switch colSort.Column { case enums.VDBBlocksColumns.Proposer: - offset = currentCursor.Proposer + offset = cursor.Proposer case enums.VDBBlocksColumns.Block: - offset = currentCursor.Block - if !currentCursor.Block.Valid { + offset = cursor.Block + if !cursor.Block.Valid { offset = nil } case enums.VDBBlocksColumns.Status: - offset = fmt.Sprintf("%d", currentCursor.Status) // type of 'status' column is text for some reason + offset = fmt.Sprintf("%d", cursor.Status) // type of 'status' column is text for some reason case enums.VDBBlocksColumns.ProposerReward: - offset = currentCursor.Reward + offset = cursor.Reward } - order, directions := applySortAndPagination(defaultColumns, t.SortColumn{Column: colSort.Column.ToExpr(), Desc: colSort.Desc, Offset: offset}, currentCursor.GenericCursor) + order, directions := applySortAndPagination(defaultColumns, t.SortColumn{Column: colSort.Column.ToExpr(), Desc: colSort.Desc, Offset: offset}, cursor.GenericCursor) blocksDs = goqu.Dialect("postgres").From(goqu.T("past_blocks_cte")). With("past_blocks_cte", blocksDs). // encapsulate so we can use selected fields Order(order...) @@ -205,9 +197,9 @@ func (d *DataAccessService) GetValidatorDashboardBlocks(ctx context.Context, das latestSlot := cache.LatestSlot.Get() onlyPrimarySort := colSort.Column == enums.VDBBlockSlot if !(onlyPrimarySort || colSort.Column == enums.VDBBlockBlock) || - !currentCursor.IsValid() || - currentCursor.Slot > latestSlot+1 || - colSort.Desc == currentCursor.Reverse { + !cursor.IsValid() || + cursor.Slot > latestSlot+1 || + colSort.Desc == cursor.Reverse { dutiesInfo, err := d.services.GetCurrentDutiesInfo() if err == nil { if dashboardId.Validators == nil { @@ -326,7 +318,7 @@ func (d *DataAccessService) GetValidatorDashboardBlocks(ctx context.Context, das if moreDataFlag { proposals = proposals[:len(proposals)-1] } - if currentCursor.IsReverse() { + if cursor.IsReverse() { slices.Reverse(proposals) } @@ -408,11 +400,11 @@ func (d *DataAccessService) GetValidatorDashboardBlocks(ctx context.Context, das contractIdx += 1 } } - if !moreDataFlag && !currentCursor.IsValid() { + if !moreDataFlag && !cursor.IsValid() { // No paging required return data, &t.Paging{}, nil } - p, err := utils.GetPagingFromData(proposals, currentCursor, moreDataFlag) + p, err := utils.GetPagingFromData(proposals, cursor, moreDataFlag) if err != nil { return nil, nil, err } diff --git a/backend/pkg/api/data_access/vdb_deposits.go b/backend/pkg/api/data_access/vdb_deposits.go index 0f81e1d93..dcd3b772c 100644 --- a/backend/pkg/api/data_access/vdb_deposits.go +++ b/backend/pkg/api/data_access/vdb_deposits.go @@ -20,17 +20,8 @@ import ( "github.com/shopspring/decimal" ) -func (d *DataAccessService) GetValidatorDashboardElDeposits(ctx context.Context, dashboardId t.VDBId, cursor string, limit uint64) ([]t.VDBExecutionDepositsTableRow, *t.Paging, error) { - var err error +func (d *DataAccessService) GetValidatorDashboardElDeposits(ctx context.Context, dashboardId t.VDBId, cursor t.ELDepositsCursor, limit uint64) ([]t.VDBExecutionDepositsTableRow, *t.Paging, error) { currentDirection := enums.DESC // TODO: expose over parameter - var currentCursor t.ELDepositsCursor - - if cursor != "" { - currentCursor, err = utils.StringToCursor[t.ELDepositsCursor](cursor) - if err != nil { - return nil, nil, fmt.Errorf("failed to parse passed cursor as ELDepositsCursor: %w", err) - } - } // Resolve validator indices to pubkeys byteaArray, err := d.getValidatorPubkeys(dashboardId) @@ -88,12 +79,12 @@ func (d *DataAccessService) GetValidatorDashboardElDeposits(ctx context.Context, params := []interface{}{filter} filterFragment := ` ORDER BY ed.block_number DESC, ed.log_index DESC` - if currentCursor.IsValid() { + if cursor.IsValid() { filterFragment = ` AND (ed.block_number < $2 or (ed.block_number = $2 and ed.log_index < $3)) ` + filterFragment - params = append(params, currentCursor.BlockNumber, currentCursor.LogIndex) + params = append(params, cursor.BlockNumber, cursor.LogIndex) } - if currentDirection == enums.ASC && !currentCursor.IsReverse() || currentDirection == enums.DESC && currentCursor.IsReverse() { + if currentDirection == enums.ASC && !cursor.IsReverse() || currentDirection == enums.DESC && cursor.IsReverse() { filterFragment = strings.Replace(strings.Replace(filterFragment, "<", ">", -1), "DESC", "ASC", -1) } @@ -194,7 +185,7 @@ func (d *DataAccessService) GetValidatorDashboardElDeposits(ctx context.Context, var paging t.Paging moreDataFlag := len(responseData) > int(limit) - if !moreDataFlag && !currentCursor.IsValid() { + if !moreDataFlag && !cursor.IsValid() { // No paging required return responseData, &paging, nil } @@ -204,13 +195,13 @@ func (d *DataAccessService) GetValidatorDashboardElDeposits(ctx context.Context, data = data[:len(data)-1] } - if currentCursor.IsReverse() { + if cursor.IsReverse() { // Invert query result so response matches requested direction slices.Reverse(responseData) slices.Reverse(data) } - p, err := utils.GetPagingFromData(data, currentCursor, moreDataFlag) + p, err := utils.GetPagingFromData(data, cursor, moreDataFlag) if err != nil { return nil, nil, fmt.Errorf("failed to get paging: %w", err) } @@ -218,17 +209,8 @@ func (d *DataAccessService) GetValidatorDashboardElDeposits(ctx context.Context, return responseData, p, nil } -func (d *DataAccessService) GetValidatorDashboardClDeposits(ctx context.Context, dashboardId t.VDBId, cursor string, limit uint64) ([]t.VDBConsensusDepositsTableRow, *t.Paging, error) { - var err error +func (d *DataAccessService) GetValidatorDashboardClDeposits(ctx context.Context, dashboardId t.VDBId, cursor t.CLDepositsCursor, limit uint64) ([]t.VDBConsensusDepositsTableRow, *t.Paging, error) { currentDirection := enums.DESC // TODO: expose over parameter - var currentCursor t.CLDepositsCursor - - if cursor != "" { - currentCursor, err = utils.StringToCursor[t.CLDepositsCursor](cursor) - if err != nil { - return nil, nil, fmt.Errorf("failed to parse passed cursor as CLDepositsCursor: %w", err) - } - } // Resolve validator indices to pubkeys byteaArray, err := d.getValidatorPubkeys(dashboardId) @@ -279,12 +261,12 @@ func (d *DataAccessService) GetValidatorDashboardClDeposits(ctx context.Context, params := []interface{}{filter} filterFragment := ` ORDER BY bd.block_slot DESC, bd.block_index DESC` - if currentCursor.IsValid() { + if cursor.IsValid() { filterFragment = ` AND (bd.block_slot < $2 or (bd.block_slot = $2 and bd.block_index < $3)) ` + filterFragment - params = append(params, currentCursor.Slot, currentCursor.SlotIndex) + params = append(params, cursor.Slot, cursor.SlotIndex) } - if currentDirection == enums.ASC && !currentCursor.IsReverse() || currentDirection == enums.DESC && currentCursor.IsReverse() { + if currentDirection == enums.ASC && !cursor.IsReverse() || currentDirection == enums.DESC && cursor.IsReverse() { filterFragment = strings.Replace(strings.Replace(filterFragment, "<", ">", -1), "DESC", "ASC", -1) } @@ -334,7 +316,7 @@ func (d *DataAccessService) GetValidatorDashboardClDeposits(ctx context.Context, var paging t.Paging moreDataFlag := len(responseData) > int(limit) - if !moreDataFlag && !currentCursor.IsValid() { + if !moreDataFlag && !cursor.IsValid() { // No paging required return responseData, &paging, nil } @@ -344,13 +326,13 @@ func (d *DataAccessService) GetValidatorDashboardClDeposits(ctx context.Context, data = data[:len(data)-1] } - if currentCursor.IsReverse() { + if cursor.IsReverse() { // Invert query result so response matches requested direction slices.Reverse(responseData) slices.Reverse(data) } - p, err := utils.GetPagingFromData(data, currentCursor, moreDataFlag) + p, err := utils.GetPagingFromData(data, cursor, moreDataFlag) if err != nil { return nil, nil, fmt.Errorf("failed to get paging: %w", err) } diff --git a/backend/pkg/api/data_access/vdb_management.go b/backend/pkg/api/data_access/vdb_management.go index 7ca61bffd..5fd198ebd 100644 --- a/backend/pkg/api/data_access/vdb_management.go +++ b/backend/pkg/api/data_access/vdb_management.go @@ -613,17 +613,7 @@ func (d *DataAccessService) GetValidatorDashboardGroupCount(ctx context.Context, return count, err } -func (d *DataAccessService) GetValidatorDashboardValidators(ctx context.Context, dashboardId t.VDBId, groupId int64, cursor string, colSort t.Sort[enums.VDBManageValidatorsColumn], search t.VDBManageValidatorsSearch, limit uint64) ([]t.VDBManageValidatorsTableRow, *t.Paging, error) { - // Initialize the cursor - var currentCursor t.ValidatorsCursor - var err error - if cursor != "" { - currentCursor, err = utils.StringToCursor[t.ValidatorsCursor](cursor) - if err != nil { - return nil, nil, fmt.Errorf("failed to parse passed cursor as ValidatorsCursor: %w", err) - } - } - +func (d *DataAccessService) GetValidatorDashboardValidators(ctx context.Context, dashboardId t.VDBId, groupId int64, cursor t.ValidatorsCursor, colSort t.Sort[enums.VDBManageValidatorsColumn], search t.VDBManageValidatorsSearch, limit uint64) ([]t.VDBManageValidatorsTableRow, *t.Paging, error) { type ValidatorGroupInfo struct { GroupId uint64 GroupName string @@ -751,9 +741,9 @@ func (d *DataAccessService) GetValidatorDashboardValidators(ctx context.Context, // Find the index for the cursor and limit the data var cursorIndex uint64 - if currentCursor.IsValid() { + if cursor.IsValid() { for idx, row := range data { - if row.Index == currentCursor.Index { + if row.Index == cursor.Index { cursorIndex = uint64(idx) break } @@ -761,7 +751,7 @@ func (d *DataAccessService) GetValidatorDashboardValidators(ctx context.Context, } var result []t.VDBManageValidatorsTableRow - if currentCursor.IsReverse() { + if cursor.IsReverse() { // opposite direction var limitCutoff uint64 if cursorIndex > limit+1 { @@ -769,7 +759,7 @@ func (d *DataAccessService) GetValidatorDashboardValidators(ctx context.Context, } result = data[limitCutoff:cursorIndex] } else { - if currentCursor.IsValid() { + if cursor.IsValid() { cursorIndex++ } limitCutoff := utilMath.MinU64(cursorIndex+limit+1, uint64(len(data))) @@ -778,21 +768,21 @@ func (d *DataAccessService) GetValidatorDashboardValidators(ctx context.Context, // flag if above limit moreDataFlag := len(result) > int(limit) - if !moreDataFlag && !currentCursor.IsValid() { + if !moreDataFlag && !cursor.IsValid() { // no paging required return result, &paging, nil } // remove the last entry from data as it is only required for the check if moreDataFlag { - if currentCursor.IsReverse() { + if cursor.IsReverse() { result = result[1:] } else { result = result[:len(result)-1] } } - p, err := utils.GetPagingFromData(result, currentCursor, moreDataFlag) + p, err := utils.GetPagingFromData(result, cursor, moreDataFlag) if err != nil { return nil, nil, fmt.Errorf("failed to get paging: %w", err) } diff --git a/backend/pkg/api/data_access/vdb_rewards.go b/backend/pkg/api/data_access/vdb_rewards.go index 7f68e1b64..1957fa7ae 100644 --- a/backend/pkg/api/data_access/vdb_rewards.go +++ b/backend/pkg/api/data_access/vdb_rewards.go @@ -22,25 +22,16 @@ import ( "golang.org/x/sync/errgroup" ) -func (d *DataAccessService) GetValidatorDashboardRewards(ctx context.Context, dashboardId t.VDBId, cursor string, colSort t.Sort[enums.VDBRewardsColumn], search string, limit uint64, protocolModes t.VDBProtocolModes) ([]t.VDBRewardsTableRow, *t.Paging, error) { +func (d *DataAccessService) GetValidatorDashboardRewards(ctx context.Context, dashboardId t.VDBId, cursor t.RewardsCursor, colSort t.Sort[enums.VDBRewardsColumn], search string, limit uint64, protocolModes t.VDBProtocolModes) ([]t.VDBRewardsTableRow, *t.Paging, error) { // @DATA-ACCESS incorporate protocolModes result := make([]t.VDBRewardsTableRow, 0) var paging t.Paging wg := errgroup.Group{} - - // Initialize the cursor - var currentCursor t.RewardsCursor var err error - if cursor != "" { - currentCursor, err = utils.StringToCursor[t.RewardsCursor](cursor) - if err != nil { - return nil, nil, fmt.Errorf("failed to parse passed cursor as RewardsCursor: %w", err) - } - } // Prepare the sorting - isReverseDirection := (colSort.Desc && !currentCursor.IsReverse()) || (!colSort.Desc && currentCursor.IsReverse()) + isReverseDirection := (colSort.Desc && !cursor.IsReverse()) || (!colSort.Desc && cursor.IsReverse()) sortSearchDirection := ">" if isReverseDirection { sortSearchDirection = "<" @@ -122,28 +113,28 @@ func (d *DataAccessService) GetValidatorDashboardRewards(ctx context.Context, da Where(goqu.L("e.validator_index IN (SELECT validator_index FROM validators)")) elDs = elDs. Where(goqu.L("v.dashboard_id = ?", dashboardId.Id)) - if currentCursor.IsValid() { - if currentCursor.IsReverse() { - if currentCursor.GroupId == t.AllGroups { + if cursor.IsValid() { + if cursor.IsReverse() { + if cursor.GroupId == t.AllGroups { // The cursor is on the total rewards so get the data for all groups excluding the cursor epoch - rewardsDs = rewardsDs.Where(goqu.L(fmt.Sprintf("e.epoch_timestamp %s fromUnixTimestamp(?)", sortSearchDirection), utils.EpochToTime(currentCursor.Epoch).Unix())) - elDs = elDs.Where(goqu.L(fmt.Sprintf("b.epoch %s ?", sortSearchDirection), currentCursor.Epoch)) + rewardsDs = rewardsDs.Where(goqu.L(fmt.Sprintf("e.epoch_timestamp %s fromUnixTimestamp(?)", sortSearchDirection), utils.EpochToTime(cursor.Epoch).Unix())) + elDs = elDs.Where(goqu.L(fmt.Sprintf("b.epoch %s ?", sortSearchDirection), cursor.Epoch)) } else { // The cursor is on a specific group, get the data for the whole epoch since we could need it for the total rewards - rewardsDs = rewardsDs.Where(goqu.L(fmt.Sprintf("e.epoch_timestamp %s= fromUnixTimestamp(?)", sortSearchDirection), utils.EpochToTime(currentCursor.Epoch).Unix())) - elDs = elDs.Where(goqu.L(fmt.Sprintf("b.epoch %s= ?", sortSearchDirection), currentCursor.Epoch)) + rewardsDs = rewardsDs.Where(goqu.L(fmt.Sprintf("e.epoch_timestamp %s= fromUnixTimestamp(?)", sortSearchDirection), utils.EpochToTime(cursor.Epoch).Unix())) + elDs = elDs.Where(goqu.L(fmt.Sprintf("b.epoch %s= ?", sortSearchDirection), cursor.Epoch)) } } else { - if currentCursor.GroupId == t.AllGroups { + if cursor.GroupId == t.AllGroups { // The cursor is on the total rewards so get the data for all groups including the cursor epoch - rewardsDs = rewardsDs.Where(goqu.L(fmt.Sprintf("e.epoch_timestamp %s= fromUnixTimestamp(?)", sortSearchDirection), utils.EpochToTime(currentCursor.Epoch).Unix())) - elDs = elDs.Where(goqu.L(fmt.Sprintf("b.epoch %s= ?", sortSearchDirection), currentCursor.Epoch)) + rewardsDs = rewardsDs.Where(goqu.L(fmt.Sprintf("e.epoch_timestamp %s= fromUnixTimestamp(?)", sortSearchDirection), utils.EpochToTime(cursor.Epoch).Unix())) + elDs = elDs.Where(goqu.L(fmt.Sprintf("b.epoch %s= ?", sortSearchDirection), cursor.Epoch)) } else { // The cursor is on a specific group so get the data for groups before/after it rewardsDs = rewardsDs.Where(goqu.L(fmt.Sprintf("(e.epoch_timestamp %[1]s fromUnixTimestamp(?) OR (e.epoch_timestamp = fromUnixTimestamp(?) AND v.group_id %[1]s ?))", sortSearchDirection), - utils.EpochToTime(currentCursor.Epoch).Unix(), utils.EpochToTime(currentCursor.Epoch).Unix(), currentCursor.GroupId)) + utils.EpochToTime(cursor.Epoch).Unix(), utils.EpochToTime(cursor.Epoch).Unix(), cursor.GroupId)) elDs = elDs.Where(goqu.L(fmt.Sprintf("(b.epoch %[1]s ? OR (b.epoch = ? AND v.group_id %[1]s ?))", sortSearchDirection), - currentCursor.Epoch, currentCursor.Epoch, currentCursor.GroupId)) + cursor.Epoch, cursor.Epoch, cursor.GroupId)) } } } @@ -262,9 +253,9 @@ func (d *DataAccessService) GetValidatorDashboardRewards(ctx context.Context, da Where(goqu.L("b.proposer = ANY(?)", pq.Array(dashboardId.Validators))). GroupBy(goqu.L("b.epoch")) - if currentCursor.IsValid() { - rewardsDs = rewardsDs.Where(goqu.L(fmt.Sprintf("e.epoch_timestamp %s fromUnixTimestamp(?)", sortSearchDirection), utils.EpochToTime(currentCursor.Epoch).Unix())) - elDs = elDs.Where(goqu.L(fmt.Sprintf("b.epoch %s ?", sortSearchDirection), currentCursor.Epoch)) + if cursor.IsValid() { + rewardsDs = rewardsDs.Where(goqu.L(fmt.Sprintf("e.epoch_timestamp %s fromUnixTimestamp(?)", sortSearchDirection), utils.EpochToTime(cursor.Epoch).Unix())) + elDs = elDs.Where(goqu.L(fmt.Sprintf("b.epoch %s ?", sortSearchDirection), cursor.Epoch)) } if search != "" { if epochSearch == -1 && indexSearch == -1 { @@ -464,15 +455,15 @@ func (d *DataAccessService) GetValidatorDashboardRewards(ctx context.Context, da } // Reverse the data if the cursor is reversed to correct it to the requested direction - if currentCursor.IsReverse() { + if cursor.IsReverse() { slices.Reverse(resultWoTotal) } // Place the total rewards in the result data at the correct position and ignore group data that is not searched for // Ascending or descending order makes no difference but the cursor direction does previousEpoch := int64(-1) - if currentCursor.IsValid() && !currentCursor.IsReverse() { - previousEpoch = int64(currentCursor.Epoch) + if cursor.IsValid() && !cursor.IsReverse() { + previousEpoch = int64(cursor.Epoch) } for _, res := range resultWoTotal { if previousEpoch != int64(res.Epoch) { @@ -482,7 +473,7 @@ func (d *DataAccessService) GetValidatorDashboardRewards(ctx context.Context, da } // If we reach a specific group cursor which should only happen if the cursor is reversed don't include it and stop - if currentCursor.IsReverse() && currentCursor.Epoch == res.Epoch && currentCursor.GroupId == res.GroupId { + if cursor.IsReverse() && cursor.Epoch == res.Epoch && cursor.GroupId == res.GroupId { break } // If we don't search for specific groups or the group is in the search add the row @@ -494,21 +485,21 @@ func (d *DataAccessService) GetValidatorDashboardRewards(ctx context.Context, da // Flag if above limit moreDataFlag := len(result) > int(limit) - if !moreDataFlag && !currentCursor.IsValid() { + if !moreDataFlag && !cursor.IsValid() { // No paging required return result, &paging, nil } // Remove the last entries from data if moreDataFlag { - if currentCursor.IsReverse() { + if cursor.IsReverse() { result = result[len(result)-int(limit):] } else { result = result[:limit] } } - p, err := utils.GetPagingFromData(result, currentCursor, moreDataFlag) + p, err := utils.GetPagingFromData(result, cursor, moreDataFlag) if err != nil { return nil, nil, fmt.Errorf("failed to get paging: %w", err) } @@ -903,7 +894,7 @@ func (d *DataAccessService) GetValidatorDashboardRewardsChart(ctx context.Contex return &result, nil } -func (d *DataAccessService) GetValidatorDashboardDuties(ctx context.Context, dashboardId t.VDBId, epoch uint64, groupId int64, cursor string, colSort t.Sort[enums.VDBDutiesColumn], search string, limit uint64, protocolModes t.VDBProtocolModes) ([]t.VDBEpochDutiesTableRow, *t.Paging, error) { +func (d *DataAccessService) GetValidatorDashboardDuties(ctx context.Context, dashboardId t.VDBId, epoch uint64, groupId int64, cursor t.ValidatorDutiesCursor, colSort t.Sort[enums.VDBDutiesColumn], search string, limit uint64, protocolModes t.VDBProtocolModes) ([]t.VDBEpochDutiesTableRow, *t.Paging, error) { result := make([]t.VDBEpochDutiesTableRow, 0) var paging t.Paging @@ -914,18 +905,8 @@ func (d *DataAccessService) GetValidatorDashboardDuties(ctx context.Context, das groupId = t.AllGroups } - // Initialize the cursor - var currentCursor t.ValidatorDutiesCursor - var err error - if cursor != "" { - currentCursor, err = utils.StringToCursor[t.ValidatorDutiesCursor](cursor) - if err != nil { - return nil, nil, fmt.Errorf("failed to parse passed cursor as ValidatorDutiesCursor: %w", err) - } - } - // Prepare the sorting - isReverseDirection := (colSort.Desc && !currentCursor.IsReverse()) || (!colSort.Desc && currentCursor.IsReverse()) + isReverseDirection := (colSort.Desc && !cursor.IsReverse()) || (!colSort.Desc && cursor.IsReverse()) // Analyze the search term indexSearch := int64(-1) @@ -1100,7 +1081,7 @@ func (d *DataAccessService) GetValidatorDashboardDuties(ctx context.Context, das return nil }) - err = wg.Wait() + err := wg.Wait() if err != nil { return nil, nil, fmt.Errorf("error retrieving validator dashboard rewards data: %v", err) } @@ -1234,11 +1215,11 @@ func (d *DataAccessService) GetValidatorDashboardDuties(ctx context.Context, das }) // Remove data before the cursor - if currentCursor.IsValid() { + if cursor.IsValid() { cursorIndex := -1 for idx, cursorEntry := range cursorData { - if cursorEntry.Index == currentCursor.Index && cursorEntry.Reward.Equal(currentCursor.Reward) { + if cursorEntry.Index == cursor.Index && cursorEntry.Reward.Equal(cursor.Reward) { cursorIndex = idx break } @@ -1253,7 +1234,7 @@ func (d *DataAccessService) GetValidatorDashboardDuties(ctx context.Context, das // Flag if above limit moreDataFlag := len(result) > int(limit) - if !moreDataFlag && !currentCursor.IsValid() { + if !moreDataFlag && !cursor.IsValid() { // No paging required return result, &paging, nil } @@ -1265,12 +1246,12 @@ func (d *DataAccessService) GetValidatorDashboardDuties(ctx context.Context, das } // Reverse the data if the cursor is reversed to correct it to the requested direction - if currentCursor.IsReverse() { + if cursor.IsReverse() { slices.Reverse(result) slices.Reverse(cursorData) } - p, err := utils.GetPagingFromData(cursorData, currentCursor, moreDataFlag) + p, err := utils.GetPagingFromData(cursorData, cursor, moreDataFlag) if err != nil { return nil, nil, fmt.Errorf("failed to get paging: %w", err) } diff --git a/backend/pkg/api/data_access/vdb_rocket_pool.go b/backend/pkg/api/data_access/vdb_rocket_pool.go index 90a94d3af..35eba1e80 100644 --- a/backend/pkg/api/data_access/vdb_rocket_pool.go +++ b/backend/pkg/api/data_access/vdb_rocket_pool.go @@ -7,7 +7,7 @@ import ( t "github.com/gobitfly/beaconchain/pkg/api/types" ) -func (d *DataAccessService) GetValidatorDashboardRocketPool(ctx context.Context, dashboardId t.VDBId, cursor string, colSort t.Sort[enums.VDBRocketPoolColumn], search string, limit uint64) ([]t.VDBRocketPoolTableRow, *t.Paging, error) { +func (d *DataAccessService) GetValidatorDashboardRocketPool(ctx context.Context, dashboardId t.VDBId, cursor t.VDBRocketPoolCursor, colSort t.Sort[enums.VDBRocketPoolColumn], search string, limit uint64) ([]t.VDBRocketPoolTableRow, *t.Paging, error) { // TODO @DATA-ACCESS return d.dummy.GetValidatorDashboardRocketPool(ctx, dashboardId, cursor, colSort, search, limit) } @@ -17,7 +17,7 @@ func (d *DataAccessService) GetValidatorDashboardTotalRocketPool(ctx context.Con return d.dummy.GetValidatorDashboardTotalRocketPool(ctx, dashboardId, search) } -func (d *DataAccessService) GetValidatorDashboardRocketPoolMinipools(ctx context.Context, dashboardId t.VDBId, node, cursor string, colSort t.Sort[enums.VDBRocketPoolMinipoolsColumn], search string, limit uint64) ([]t.VDBRocketPoolMinipoolsTableRow, *t.Paging, error) { +func (d *DataAccessService) GetValidatorDashboardRocketPoolMinipools(ctx context.Context, dashboardId t.VDBId, node string, cursor t.VDBRocketPoolMinipoolsCursor, colSort t.Sort[enums.VDBRocketPoolMinipoolsColumn], search string, limit uint64) ([]t.VDBRocketPoolMinipoolsTableRow, *t.Paging, error) { // TODO @DATA-ACCESS return d.dummy.GetValidatorDashboardRocketPoolMinipools(ctx, dashboardId, node, cursor, colSort, search, limit) } diff --git a/backend/pkg/api/data_access/vdb_summary.go b/backend/pkg/api/data_access/vdb_summary.go index 6312e9185..24e463cee 100644 --- a/backend/pkg/api/data_access/vdb_summary.go +++ b/backend/pkg/api/data_access/vdb_summary.go @@ -27,6 +27,7 @@ import ( ) func (d *DataAccessService) GetValidatorDashboardSummary(ctx context.Context, dashboardId t.VDBId, period enums.TimePeriod, cursor string, colSort t.Sort[enums.VDBSummaryColumn], search t.VDBSummarySearch, limit uint64, protocolModes t.VDBProtocolModes) ([]t.VDBSummaryTableRow, *t.Paging, error) { + // TODO either implement or remove cursor parameter // @DATA-ACCESS incorporate protocolModes result := make([]t.VDBSummaryTableRow, 0) var paging t.Paging diff --git a/backend/pkg/api/data_access/vdb_withdrawals.go b/backend/pkg/api/data_access/vdb_withdrawals.go index 93124cd73..a7c47b479 100644 --- a/backend/pkg/api/data_access/vdb_withdrawals.go +++ b/backend/pkg/api/data_access/vdb_withdrawals.go @@ -24,24 +24,14 @@ import ( "github.com/shopspring/decimal" ) -func (d *DataAccessService) GetValidatorDashboardWithdrawals(ctx context.Context, dashboardId t.VDBId, cursor string, colSort t.Sort[enums.VDBWithdrawalsColumn], search string, limit uint64, protocolModes t.VDBProtocolModes) ([]t.VDBWithdrawalsTableRow, *t.Paging, error) { +func (d *DataAccessService) GetValidatorDashboardWithdrawals(ctx context.Context, dashboardId t.VDBId, cursor t.WithdrawalsCursor, colSort t.Sort[enums.VDBWithdrawalsColumn], search string, limit uint64, protocolModes t.VDBProtocolModes) ([]t.VDBWithdrawalsTableRow, *t.Paging, error) { result := make([]t.VDBWithdrawalsTableRow, 0) var paging t.Paging - // Initialize the cursor - var currentCursor t.WithdrawalsCursor - var err error - if cursor != "" { - currentCursor, err = utils.StringToCursor[t.WithdrawalsCursor](cursor) - if err != nil { - return nil, nil, fmt.Errorf("failed to parse passed cursor as WithdrawalsCursor: %w", err) - } - } - // Prepare the sorting sortSearchDirection := ">" sortSearchOrder := " ASC" - if (colSort.Desc && !currentCursor.IsReverse()) || (!colSort.Desc && currentCursor.IsReverse()) { + if (colSort.Desc && !cursor.IsReverse()) || (!colSort.Desc && cursor.IsReverse()) { sortSearchDirection = "<" sortSearchOrder = " DESC" } @@ -147,28 +137,28 @@ func (d *DataAccessService) GetValidatorDashboardWithdrawals(ctx context.Context case enums.VDBWithdrawalsColumns.Epoch, enums.VDBWithdrawalsColumns.Slot: case enums.VDBWithdrawalsColumns.Index: sortColName = "w.validatorindex" - sortColCursor = currentCursor.Index + sortColCursor = cursor.Index case enums.VDBWithdrawalsColumns.Recipient: sortColName = "w.address" - sortColCursor = currentCursor.Recipient + sortColCursor = cursor.Recipient case enums.VDBWithdrawalsColumns.Amount: sortColName = "w.amount" - sortColCursor = currentCursor.Amount + sortColCursor = cursor.Amount } if colSort.Column == enums.VDBWithdrawalsColumns.Epoch || colSort.Column == enums.VDBWithdrawalsColumns.Slot { - if currentCursor.IsValid() { + if cursor.IsValid() { // If we have a valid cursor only check the results before/after it - queryParams = append(queryParams, currentCursor.Slot, currentCursor.WithdrawalIndex) + queryParams = append(queryParams, cursor.Slot, cursor.WithdrawalIndex) whereQuery += fmt.Sprintf(" AND (w.block_slot%[1]s$%[2]d OR (w.block_slot=$%[2]d AND w.withdrawalindex%[1]s$%[3]d))", sortSearchDirection, len(queryParams)-1, len(queryParams)) } orderQuery = fmt.Sprintf(" ORDER BY w.block_slot %[1]s, w.withdrawalindex %[1]s", sortSearchOrder) } else { - if currentCursor.IsValid() { + if cursor.IsValid() { // If we have a valid cursor only check the results before/after it - queryParams = append(queryParams, sortColCursor, currentCursor.Slot, currentCursor.WithdrawalIndex) + queryParams = append(queryParams, sortColCursor, cursor.Slot, cursor.WithdrawalIndex) // The additional WHERE requirement is // WHERE sortColName>cursor OR (sortColName=cursor AND (block_slot>cursor OR (block_slot=cursor AND withdrawalindex>cursor))) @@ -255,14 +245,14 @@ func (d *DataAccessService) GetValidatorDashboardWithdrawals(ctx context.Context } // Reverse the data if the cursor is reversed to correct it to the requested direction - if currentCursor.IsReverse() { + if cursor.IsReverse() { slices.Reverse(result) slices.Reverse(cursorData) } // Find the next withdrawal if we are currently at the first page // If we have a prev_cursor but not enough data it means the next data is missing - if !currentCursor.IsValid() || (currentCursor.IsReverse() && len(result) < int(limit)) { + if !cursor.IsValid() || (cursor.IsReverse() && len(result) < int(limit)) { nextData, err := d.getNextWithdrawalRow(validators) if err != nil { return nil, nil, err @@ -282,7 +272,7 @@ func (d *DataAccessService) GetValidatorDashboardWithdrawals(ctx context.Context // Flag if above limit moreDataFlag = moreDataFlag || len(result) > int(limit) - if !moreDataFlag && !currentCursor.IsValid() { + if !moreDataFlag && !cursor.IsValid() { // No paging required return result, &paging, nil } @@ -294,7 +284,7 @@ func (d *DataAccessService) GetValidatorDashboardWithdrawals(ctx context.Context } } - p, err := utils.GetPagingFromData(cursorData, currentCursor, moreDataFlag) + p, err := utils.GetPagingFromData(cursorData, cursor, moreDataFlag) if err != nil { return nil, nil, fmt.Errorf("failed to get paging: %w", err) } diff --git a/backend/pkg/api/handlers/input_validation.go b/backend/pkg/api/handlers/input_validation.go index 46ca8643b..4d205a0d9 100644 --- a/backend/pkg/api/handlers/input_validation.go +++ b/backend/pkg/api/handlers/input_validation.go @@ -15,6 +15,7 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/gobitfly/beaconchain/pkg/api/enums" "github.com/gobitfly/beaconchain/pkg/api/types" + "github.com/gobitfly/beaconchain/pkg/commons/utils" "github.com/gorilla/mux" "github.com/invopop/jsonschema" "github.com/shopspring/decimal" @@ -48,7 +49,6 @@ var searchEnumsRegexMapping = map[types.SearchType]*regexp.Regexp{ types.SearchTypeWithdrawalCredential: reWithdrawalCredential, types.SearchTypeEnsName: reEnsName, types.SearchTypeGraffiti: reGraffiti, - types.SearchTypeCursor: reCursor, types.SearchTypeEmail: reEmail, types.SearchTypePassword: rePassword, types.SearchTypeEmailUserToken: reEmailUserToken, @@ -365,15 +365,15 @@ func (v *validationError) checkUintMinMax(param string, min uint64, max uint64, return checkMinMax(v, v.checkUint(param, paramName), min, max, paramName) } -type Paging struct { - cursor string +type Paging[T types.CursorLike] struct { + cursor T limit uint64 search string } -func (v *validationError) checkPagingParams(q url.Values) Paging { - paging := Paging{ - cursor: q.Get("cursor"), +func checkPagingParams[T types.CursorLike](v *validationError, q url.Values) Paging[T] { + paging := Paging[T]{ + cursor: *new(T), limit: defaultReturnLimit, search: q.Get("search"), } @@ -382,8 +382,12 @@ func (v *validationError) checkPagingParams(q url.Values) Paging { paging.limit = v.checkUintMinMax(limitStr, 1, maxQueryLimit, "limit") } - if paging.cursor != "" { - paging.cursor = v.checkRegex(reCursor, paging.cursor, "cursor") + if q.Get("cursor") != "" { + cursor, err := utils.StringToCursor[T](v.checkRegex(reCursor, q.Get("cursor"), "cursor")) + if err != nil { + v.add("cursor", fmt.Sprintf("give value '%s' is not valid: %v", q.Get("cursor"), err)) + } + paging.cursor = cursor } return paging diff --git a/backend/pkg/api/handlers/internal.go b/backend/pkg/api/handlers/internal.go index 83bb4faf2..2db63bd7e 100644 --- a/backend/pkg/api/handlers/internal.go +++ b/backend/pkg/api/handlers/internal.go @@ -376,7 +376,7 @@ func (h *HandlerService) InternalGetValidatorDashboardMobileValidators(w http.Re return } q := r.URL.Query() - pagingParams := v.checkPagingParams(q) + pagingParams := checkPagingParams[types.VDBMobileValidatorsCursor](&v, q) period := checkEnum[enums.TimePeriod](&v, q.Get("period"), "period") sort := checkSort[enums.VDBMobileValidatorsColumn](&v, q.Get("sort")) diff --git a/backend/pkg/api/handlers/public.go b/backend/pkg/api/handlers/public.go index 182beaf68..0560aafea 100644 --- a/backend/pkg/api/handlers/public.go +++ b/backend/pkg/api/handlers/public.go @@ -657,7 +657,7 @@ func (h *HandlerService) PublicGetValidatorDashboardValidators(w http.ResponseWr } q := r.URL.Query() groupId := v.checkGroupId(q.Get("group_id"), allowEmpty) - pagingParams := v.checkPagingParams(q) + pagingParams := checkPagingParams[types.ValidatorsCursor](&v, q) sort := checkSort[enums.VDBManageValidatorsColumn](&v, q.Get("sort")) if v.hasErrors() { handleErr(w, r, v) @@ -1025,7 +1025,8 @@ func (h *HandlerService) PublicGetValidatorDashboardSummary(w http.ResponseWrite return } q := r.URL.Query() - pagingParams := v.checkPagingParams(q) + // no paging present here, TODO check if it can be removed + pagingParams := checkPagingParams[types.CursorLike](&v, q) sort := checkSort[enums.VDBSummaryColumn](&v, q.Get("sort")) protocolModes := v.checkProtocolModes(q.Get("modes")) @@ -1039,7 +1040,7 @@ func (h *HandlerService) PublicGetValidatorDashboardSummary(w http.ResponseWrite returnOk(w, r, emptyPagingResponse()) } - data, paging, err := h.getDataAccessor(r).GetValidatorDashboardSummary(r.Context(), *dashboardId, period, pagingParams.cursor, *sort, *search, pagingParams.limit, protocolModes) + data, paging, err := h.getDataAccessor(r).GetValidatorDashboardSummary(r.Context(), *dashboardId, period, "", *sort, *search, pagingParams.limit, protocolModes) if err != nil { handleErr(w, r, err) return @@ -1229,7 +1230,7 @@ func (h *HandlerService) PublicGetValidatorDashboardRewards(w http.ResponseWrite return } q := r.URL.Query() - pagingParams := v.checkPagingParams(q) + pagingParams := checkPagingParams[types.RewardsCursor](&v, q) sort := checkSort[enums.VDBRewardsColumn](&v, q.Get("sort")) protocolModes := v.checkProtocolModes(q.Get("modes")) if v.hasErrors() { @@ -1352,7 +1353,7 @@ func (h *HandlerService) PublicGetValidatorDashboardDuties(w http.ResponseWriter q := r.URL.Query() groupId := v.checkGroupId(q.Get("group_id"), allowEmpty) epoch := v.checkUint(vars["epoch"], "epoch") - pagingParams := v.checkPagingParams(q) + pagingParams := checkPagingParams[types.ValidatorDutiesCursor](&v, q) sort := checkSort[enums.VDBDutiesColumn](&v, q.Get("sort")) protocolModes := v.checkProtocolModes(q.Get("modes")) if v.hasErrors() { @@ -1394,7 +1395,7 @@ func (h *HandlerService) PublicGetValidatorDashboardBlocks(w http.ResponseWriter return } q := r.URL.Query() - pagingParams := v.checkPagingParams(q) + pagingParams := checkPagingParams[types.BlocksCursor](&v, q) sort := checkSort[enums.VDBBlocksColumn](&v, q.Get("sort")) protocolModes := v.checkProtocolModes(q.Get("modes")) if v.hasErrors() { @@ -1535,7 +1536,7 @@ func (h *HandlerService) PublicGetValidatorDashboardExecutionLayerDeposits(w htt handleErr(w, r, err) return } - pagingParams := v.checkPagingParams(r.URL.Query()) + pagingParams := checkPagingParams[types.ELDepositsCursor](&v, r.URL.Query()) if v.hasErrors() { handleErr(w, r, v) return @@ -1571,7 +1572,7 @@ func (h *HandlerService) PublicGetValidatorDashboardConsensusLayerDeposits(w htt handleErr(w, r, err) return } - pagingParams := v.checkPagingParams(r.URL.Query()) + pagingParams := checkPagingParams[types.CLDepositsCursor](&v, r.URL.Query()) if v.hasErrors() { handleErr(w, r, v) return @@ -1668,7 +1669,7 @@ func (h *HandlerService) PublicGetValidatorDashboardWithdrawals(w http.ResponseW handleErr(w, r, err) return } - pagingParams := v.checkPagingParams(q) + pagingParams := checkPagingParams[types.WithdrawalsCursor](&v, q) sort := checkSort[enums.VDBWithdrawalsColumn](&v, q.Get("sort")) protocolModes := v.checkProtocolModes(q.Get("modes")) if v.hasErrors() { @@ -1706,7 +1707,7 @@ func (h *HandlerService) PublicGetValidatorDashboardTotalWithdrawals(w http.Resp handleErr(w, r, err) return } - pagingParams := v.checkPagingParams(q) + pagingParams := checkPagingParams[types.CursorLike](&v, q) protocolModes := v.checkProtocolModes(q.Get("modes")) if v.hasErrors() { handleErr(w, r, v) @@ -1746,7 +1747,7 @@ func (h *HandlerService) PublicGetValidatorDashboardRocketPool(w http.ResponseWr handleErr(w, r, err) return } - pagingParams := v.checkPagingParams(q) + pagingParams := checkPagingParams[types.VDBRocketPoolCursor](&v, q) sort := checkSort[enums.VDBRocketPoolColumn](&v, q.Get("sort")) if v.hasErrors() { handleErr(w, r, v) @@ -1782,7 +1783,7 @@ func (h *HandlerService) PublicGetValidatorDashboardTotalRocketPool(w http.Respo handleErr(w, r, err) return } - pagingParams := v.checkPagingParams(q) + pagingParams := checkPagingParams[types.CursorLike](&v, q) if v.hasErrors() { handleErr(w, r, v) return @@ -1824,7 +1825,7 @@ func (h *HandlerService) PublicGetValidatorDashboardRocketPoolMinipools(w http.R } // support ENS names ? nodeAddress := v.checkAddress(vars["node_address"]) - pagingParams := v.checkPagingParams(q) + pagingParams := checkPagingParams[types.VDBRocketPoolMinipoolsCursor](&v, q) sort := checkSort[enums.VDBRocketPoolMinipoolsColumn](&v, q.Get("sort")) if v.hasErrors() { handleErr(w, r, v) @@ -1894,7 +1895,7 @@ func (h *HandlerService) PublicGetUserNotificationDashboards(w http.ResponseWrit return } q := r.URL.Query() - pagingParams := v.checkPagingParams(q) + pagingParams := checkPagingParams[types.NotificationsDashboardsCursor](&v, q) sort := checkSort[enums.NotificationDashboardsColumn](&v, q.Get("sort")) chainIds := v.checkNetworksParameter(q.Get("networks")) if v.hasErrors() { @@ -2005,7 +2006,7 @@ func (h *HandlerService) PublicGetUserNotificationMachines(w http.ResponseWriter return } q := r.URL.Query() - pagingParams := v.checkPagingParams(q) + pagingParams := checkPagingParams[types.NotificationMachinesCursor](&v, q) sort := checkSort[enums.NotificationMachinesColumn](&v, q.Get("sort")) if v.hasErrors() { handleErr(w, r, v) @@ -2044,7 +2045,7 @@ func (h *HandlerService) PublicGetUserNotificationClients(w http.ResponseWriter, return } q := r.URL.Query() - pagingParams := v.checkPagingParams(q) + pagingParams := checkPagingParams[types.NotificationClientsCursor](&v, q) sort := checkSort[enums.NotificationClientsColumn](&v, q.Get("sort")) if v.hasErrors() { handleErr(w, r, v) @@ -2083,7 +2084,7 @@ func (h *HandlerService) PublicGetUserNotificationRocketPool(w http.ResponseWrit return } q := r.URL.Query() - pagingParams := v.checkPagingParams(q) + pagingParams := checkPagingParams[types.NotificationRocketPoolsCursor](&v, q) sort := checkSort[enums.NotificationRocketPoolColumn](&v, q.Get("sort")) if v.hasErrors() { handleErr(w, r, v) @@ -2121,7 +2122,7 @@ func (h *HandlerService) PublicGetUserNotificationNetworks(w http.ResponseWriter return } q := r.URL.Query() - pagingParams := v.checkPagingParams(q) + pagingParams := checkPagingParams[types.NotificationNetworksCursor](&v, q) sort := checkSort[enums.NotificationNetworksColumn](&v, q.Get("sort")) if v.hasErrors() { handleErr(w, r, v) @@ -2495,7 +2496,7 @@ func (h *HandlerService) PublicGetUserNotificationSettingsDashboards(w http.Resp return } q := r.URL.Query() - pagingParams := v.checkPagingParams(q) + pagingParams := checkPagingParams[types.NotificationSettingsCursor](&v, q) sort := checkSort[enums.NotificationSettingsDashboardColumn](&v, q.Get("sort")) if v.hasErrors() { handleErr(w, r, v) diff --git a/backend/pkg/api/types/data_access.go b/backend/pkg/api/types/data_access.go index 16ceb8e26..e4100c4f1 100644 --- a/backend/pkg/api/types/data_access.go +++ b/backend/pkg/api/types/data_access.go @@ -117,6 +117,24 @@ type WithdrawalsCursor struct { Amount uint64 } +type VDBRocketPoolCursor struct { + GenericCursor + + // TODO +} + +type VDBRocketPoolMinipoolsCursor struct { + GenericCursor + + // TODO +} + +type VDBMobileValidatorsCursor struct { + GenericCursor + + // TODO +} + type NotificationSettingsCursor struct { GenericCursor @@ -349,7 +367,6 @@ const ( SearchTypeWithdrawalCredential SearchTypeEnsName SearchTypeGraffiti - SearchTypeCursor SearchTypeEmail SearchTypePassword SearchTypeEmailUserToken @@ -410,7 +427,6 @@ func (bs *basicSearch) GetSearches() []SearchType { SearchTypeWithdrawalCredential, SearchTypeEnsName, SearchTypeGraffiti, - SearchTypeCursor, SearchTypeEmail, SearchTypePassword, SearchTypeEmailUserToken,