From 18b30024363301df3bb7889e62bc23841e380286 Mon Sep 17 00:00:00 2001 From: remoterami Date: Fri, 21 Jun 2024 10:48:27 +0200 Subject: [PATCH 01/15] ajusted struct --- backend/pkg/api/data_access/user.go | 1 + backend/pkg/api/types/dashboard.go | 8 +++++--- frontend/types/api/dashboard.ts | 2 ++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/backend/pkg/api/data_access/user.go b/backend/pkg/api/data_access/user.go index 56a6982b1..d1fbb482c 100644 --- a/backend/pkg/api/data_access/user.go +++ b/backend/pkg/api/data_access/user.go @@ -435,6 +435,7 @@ func (d *DataAccessService) GetProductSummary() (*t.ProductSummary, error) { } func (d *DataAccessService) GetUserDashboards(userId uint64) (*t.UserDashboardsData, error) { + // TODO @recy21 Adjust to api changes: return ValidatorDashboard Archived & ArchivedReason result := &t.UserDashboardsData{} dbReturn := []struct { diff --git a/backend/pkg/api/types/dashboard.go b/backend/pkg/api/types/dashboard.go index 7d3885ae2..542982799 100644 --- a/backend/pkg/api/types/dashboard.go +++ b/backend/pkg/api/types/dashboard.go @@ -5,9 +5,11 @@ type AccountDashboard struct { Name string `json:"name"` } type ValidatorDashboard struct { - Id uint64 `json:"id"` - Name string `json:"name"` - PublicIds []VDBPublicId `json:"public_ids,omitempty"` + Id uint64 `json:"id"` + Name string `json:"name"` + PublicIds []VDBPublicId `json:"public_ids,omitempty"` + Archived bool `json:"archived"` + ArchivedReason string `json:"archived_reason,omitempty"` // dashboard_limit, validator_limit, (not present = can be restored) } type UserDashboardsData struct { ValidatorDashboards []ValidatorDashboard `json:"validator_dashboards"` diff --git a/frontend/types/api/dashboard.ts b/frontend/types/api/dashboard.ts index 932bfaefb..ab341de26 100644 --- a/frontend/types/api/dashboard.ts +++ b/frontend/types/api/dashboard.ts @@ -13,6 +13,8 @@ export interface ValidatorDashboard { id: number /* uint64 */; name: string; public_ids?: VDBPublicId[]; + archived: boolean; + archived_reason?: string; // dashboard_limit, validator_limit, (not present = can be restored) } export interface UserDashboardsData { validator_dashboards: ValidatorDashboard[]; From 8e3ef5de697f489ed06b6da01dd322949464ba7c Mon Sep 17 00:00:00 2001 From: remoterami Date: Mon, 24 Jun 2024 15:04:26 +0200 Subject: [PATCH 02/15] added archiving endpoints --- backend/pkg/api/data_access/dummy.go | 12 ++++++ backend/pkg/api/data_access/user.go | 2 +- backend/pkg/api/data_access/vdb_helpers.go | 3 ++ backend/pkg/api/data_access/vdb_management.go | 10 +++++ backend/pkg/api/handlers/internal.go | 43 +++++++++++++++++++ backend/pkg/api/handlers/public.go | 8 ++++ backend/pkg/api/router.go | 2 + backend/pkg/api/types/dashboard.go | 10 ++--- backend/pkg/api/types/validator_dashboard.go | 13 ++++++ frontend/types/api/dashboard.ts | 3 +- frontend/types/api/validator_dashboard.ts | 10 +++++ 11 files changed, 108 insertions(+), 8 deletions(-) diff --git a/backend/pkg/api/data_access/dummy.go b/backend/pkg/api/data_access/dummy.go index 5612c8b1b..8428ea040 100644 --- a/backend/pkg/api/data_access/dummy.go +++ b/backend/pkg/api/data_access/dummy.go @@ -113,6 +113,18 @@ func (d *DummyService) RemoveValidatorDashboard(dashboardId t.VDBIdPrimary) erro return nil } +func (d *DummyService) GetValidatorDashboardArchiving(dashboardId t.VDBIdPrimary) (*t.VDBArchivedData, error) { + r := t.VDBArchivedData{} + err := commonFakeData(&r) + return &r, err +} + +func (d *DummyService) UpdateValidatorDashboardArchiving(dashboardId t.VDBIdPrimary, archived bool) (*t.VDBPostArchivingReturnData, error) { + r := t.VDBPostArchivingReturnData{} + err := commonFakeData(&r) + return &r, err +} + func (d *DummyService) UpdateValidatorDashboardName(dashboardId t.VDBIdPrimary, name string) (*t.VDBPostReturnData, error) { r := t.VDBPostReturnData{} err := commonFakeData(&r) diff --git a/backend/pkg/api/data_access/user.go b/backend/pkg/api/data_access/user.go index d1fbb482c..6babe686a 100644 --- a/backend/pkg/api/data_access/user.go +++ b/backend/pkg/api/data_access/user.go @@ -435,7 +435,7 @@ func (d *DataAccessService) GetProductSummary() (*t.ProductSummary, error) { } func (d *DataAccessService) GetUserDashboards(userId uint64) (*t.UserDashboardsData, error) { - // TODO @recy21 Adjust to api changes: return ValidatorDashboard Archived & ArchivedReason + // TODO @DATA-ACCESS Adjust to api changes: return ValidatorDashboard Archived result := &t.UserDashboardsData{} dbReturn := []struct { diff --git a/backend/pkg/api/data_access/vdb_helpers.go b/backend/pkg/api/data_access/vdb_helpers.go index 37d65fc21..59863f328 100644 --- a/backend/pkg/api/data_access/vdb_helpers.go +++ b/backend/pkg/api/data_access/vdb_helpers.go @@ -16,6 +16,9 @@ type ValidatorDashboardRepository interface { CreateValidatorDashboard(userId uint64, name string, network uint64) (*t.VDBPostReturnData, error) RemoveValidatorDashboard(dashboardId t.VDBIdPrimary) error + GetValidatorDashboardArchiving(dashboardId t.VDBIdPrimary) (*t.VDBArchivedData, error) + UpdateValidatorDashboardArchiving(dashboardId t.VDBIdPrimary, archived bool) (*t.VDBPostArchivingReturnData, error) + UpdateValidatorDashboardName(dashboardId t.VDBIdPrimary, name string) (*t.VDBPostReturnData, error) GetValidatorDashboardOverview(dashboardId t.VDBId) (*t.VDBOverviewData, error) diff --git a/backend/pkg/api/data_access/vdb_management.go b/backend/pkg/api/data_access/vdb_management.go index c1f291d68..3e8ca0380 100644 --- a/backend/pkg/api/data_access/vdb_management.go +++ b/backend/pkg/api/data_access/vdb_management.go @@ -180,6 +180,16 @@ func (d *DataAccessService) RemoveValidatorDashboard(dashboardId t.VDBIdPrimary) return nil } +func (d *DataAccessService) GetValidatorDashboardArchiving(dashboardId t.VDBIdPrimary) (*t.VDBArchivedData, error) { + // TODO @DATA-ACCESS + return d.dummy.GetValidatorDashboardArchiving(dashboardId) +} + +func (d *DataAccessService) UpdateValidatorDashboardArchiving(dashboardId t.VDBIdPrimary, archived bool) (*t.VDBPostArchivingReturnData, error) { + // TODO @DATA-ACCESS + return d.dummy.UpdateValidatorDashboardArchiving(dashboardId, archived) +} + func (d *DataAccessService) UpdateValidatorDashboardName(dashboardId t.VDBIdPrimary, name string) (*t.VDBPostReturnData, error) { result := &t.VDBPostReturnData{} diff --git a/backend/pkg/api/handlers/internal.go b/backend/pkg/api/handlers/internal.go index 3a1b7afd7..4c5e84f80 100644 --- a/backend/pkg/api/handlers/internal.go +++ b/backend/pkg/api/handlers/internal.go @@ -276,6 +276,49 @@ func (h *HandlerService) InternalDeleteValidatorDashboard(w http.ResponseWriter, returnNoContent(w) } +func (h *HandlerService) InternalGetValidatorDashboardArchiving(w http.ResponseWriter, r *http.Request) { + var v validationError + dashboardId := v.checkPrimaryDashboardId(mux.Vars(r)["dashboard_id"]) + if v.hasErrors() { + handleErr(w, v) + return + } + data, err := h.dai.GetValidatorDashboardArchiving(dashboardId) + if err != nil { + handleErr(w, err) + return + } + response := types.InternalGetValidatorDashboardArchivingResponse{ + Data: *data, + } + returnOk(w, response) +} + +func (h *HandlerService) InternalPutValidatorDashboardArchiving(w http.ResponseWriter, r *http.Request) { + var v validationError + dashboardId := v.checkPrimaryDashboardId(mux.Vars(r)["dashboard_id"]) + req := struct { + Archived bool `json:"archived"` + }{} + if err := v.checkBody(&req, r); err != nil { + handleErr(w, err) + return + } + if v.hasErrors() { + handleErr(w, v) + return + } + data, err := h.dai.UpdateValidatorDashboardArchiving(dashboardId, req.Archived) + if err != nil { + handleErr(w, err) + return + } + response := types.ApiDataResponse[types.VDBPostArchivingReturnData]{ + Data: *data, + } + returnOk(w, response) +} + func (h *HandlerService) InternalPutValidatorDashboardName(w http.ResponseWriter, r *http.Request) { var v validationError dashboardId := v.checkPrimaryDashboardId(mux.Vars(r)["dashboard_id"]) diff --git a/backend/pkg/api/handlers/public.go b/backend/pkg/api/handlers/public.go index 5ef698e93..8be409bcf 100644 --- a/backend/pkg/api/handlers/public.go +++ b/backend/pkg/api/handlers/public.go @@ -111,6 +111,14 @@ func (h *HandlerService) PublicDeleteValidatorDashboard(w http.ResponseWriter, r returnNoContent(w) } +func (h *HandlerService) PublicGetValidatorDashboardArchiving(w http.ResponseWriter, r *http.Request) { + returnNoContent(w) +} + +func (h *HandlerService) PublicPutValidatorDashboardArchiving(w http.ResponseWriter, r *http.Request) { + returnNoContent(w) +} + func (h *HandlerService) PublicPostValidatorDashboardGroups(w http.ResponseWriter, r *http.Request) { returnCreated(w, nil) } diff --git a/backend/pkg/api/router.go b/backend/pkg/api/router.go index 8beee3cbe..141c45d35 100644 --- a/backend/pkg/api/router.go +++ b/backend/pkg/api/router.go @@ -225,6 +225,8 @@ func addValidatorDashboardRoutes(hs *handlers.HandlerService, publicRouter, inte endpoints := []endpoint{ {http.MethodGet, "/{dashboard_id}", hs.PublicGetValidatorDashboard, hs.InternalGetValidatorDashboard}, {http.MethodDelete, "/{dashboard_id}", hs.PublicDeleteValidatorDashboard, hs.InternalDeleteValidatorDashboard}, + {http.MethodGet, "/{dashboard_id}/archiving", hs.PublicGetValidatorDashboardArchiving, hs.InternalGetValidatorDashboardArchiving}, + {http.MethodPut, "/{dashboard_id}/archiving", hs.PublicPutValidatorDashboardArchiving, hs.InternalPutValidatorDashboardArchiving}, {http.MethodPut, "/{dashboard_id}/name", nil, hs.InternalPutValidatorDashboardName}, {http.MethodPost, "/{dashboard_id}/groups", hs.PublicPostValidatorDashboardGroups, hs.InternalPostValidatorDashboardGroups}, {http.MethodPut, "/{dashboard_id}/groups/{group_id}", hs.PublicPutValidatorDashboardGroups, hs.InternalPutValidatorDashboardGroups}, diff --git a/backend/pkg/api/types/dashboard.go b/backend/pkg/api/types/dashboard.go index 542982799..7ff5046e9 100644 --- a/backend/pkg/api/types/dashboard.go +++ b/backend/pkg/api/types/dashboard.go @@ -5,12 +5,12 @@ type AccountDashboard struct { Name string `json:"name"` } type ValidatorDashboard struct { - Id uint64 `json:"id"` - Name string `json:"name"` - PublicIds []VDBPublicId `json:"public_ids,omitempty"` - Archived bool `json:"archived"` - ArchivedReason string `json:"archived_reason,omitempty"` // dashboard_limit, validator_limit, (not present = can be restored) + Id uint64 `json:"id"` + Name string `json:"name"` + Archived bool `json:"archived"` + PublicIds []VDBPublicId `json:"public_ids,omitempty"` } + type UserDashboardsData struct { ValidatorDashboards []ValidatorDashboard `json:"validator_dashboards"` AccountDashboards []AccountDashboard `json:"account_dashboards"` diff --git a/backend/pkg/api/types/validator_dashboard.go b/backend/pkg/api/types/validator_dashboard.go index d7cc74bdb..1beee1cc4 100644 --- a/backend/pkg/api/types/validator_dashboard.go +++ b/backend/pkg/api/types/validator_dashboard.go @@ -31,6 +31,19 @@ type VDBOverviewData struct { type InternalGetValidatorDashboardResponse ApiDataResponse[VDBOverviewData] +type VDBPostArchivingReturnData struct { + Id uint64 `json:"id"` + Archived bool `json:"archived"` +} + +type VDBArchivedData struct { + Reason string `json:"reason"` // dashboard_limit, validator_limit, group_limit, none + ValidatorCount uint64 `json:"validator_count"` + GroupCount uint64 `json:"group_count"` +} + +type InternalGetValidatorDashboardArchivingResponse ApiDataResponse[VDBArchivedData] + // ------------------------------------------------------------ // Summary Tab diff --git a/frontend/types/api/dashboard.ts b/frontend/types/api/dashboard.ts index ab341de26..793e6bf93 100644 --- a/frontend/types/api/dashboard.ts +++ b/frontend/types/api/dashboard.ts @@ -12,9 +12,8 @@ export interface AccountDashboard { export interface ValidatorDashboard { id: number /* uint64 */; name: string; - public_ids?: VDBPublicId[]; archived: boolean; - archived_reason?: string; // dashboard_limit, validator_limit, (not present = can be restored) + public_ids?: VDBPublicId[]; } export interface UserDashboardsData { validator_dashboards: ValidatorDashboard[]; diff --git a/frontend/types/api/validator_dashboard.ts b/frontend/types/api/validator_dashboard.ts index 2acb42298..ef4161b22 100644 --- a/frontend/types/api/validator_dashboard.ts +++ b/frontend/types/api/validator_dashboard.ts @@ -30,6 +30,16 @@ export interface VDBOverviewData { apr: PeriodicValues>; } export type InternalGetValidatorDashboardResponse = ApiDataResponse; +export interface VDBPostArchivingReturnData { + id: number /* uint64 */; + archived: boolean; +} +export interface VDBArchivedData { + reason: string; // dashboard_limit, validator_limit, group_limit, none + validator_count: number /* uint64 */; + group_count: number /* uint64 */; +} +export type InternalGetValidatorDashboardArchivingResponse = ApiDataResponse; export interface VDBSummaryStatus { next_sync_count: number /* uint64 */; current_sync_count: number /* uint64 */; From 596ccb168785c5bc5de1391d924715aed8f9d51b Mon Sep 17 00:00:00 2001 From: remoterami Date: Fri, 12 Jul 2024 10:46:11 +0200 Subject: [PATCH 03/15] returning archival info in dashboards overview call --- backend/pkg/api/data_access/dummy.go | 6 ------ backend/pkg/api/data_access/user.go | 2 +- backend/pkg/api/data_access/vdb_helpers.go | 1 - backend/pkg/api/data_access/vdb_management.go | 5 ----- backend/pkg/api/handlers/internal.go | 18 ------------------ backend/pkg/api/handlers/public.go | 4 ---- backend/pkg/api/router.go | 1 - backend/pkg/api/types/dashboard.go | 11 +++++++---- backend/pkg/api/types/validator_dashboard.go | 8 -------- frontend/types/api/dashboard.ts | 5 ++++- frontend/types/api/validator_dashboard.ts | 6 ------ 11 files changed, 12 insertions(+), 55 deletions(-) diff --git a/backend/pkg/api/data_access/dummy.go b/backend/pkg/api/data_access/dummy.go index 8428ea040..e1257fca5 100644 --- a/backend/pkg/api/data_access/dummy.go +++ b/backend/pkg/api/data_access/dummy.go @@ -113,12 +113,6 @@ func (d *DummyService) RemoveValidatorDashboard(dashboardId t.VDBIdPrimary) erro return nil } -func (d *DummyService) GetValidatorDashboardArchiving(dashboardId t.VDBIdPrimary) (*t.VDBArchivedData, error) { - r := t.VDBArchivedData{} - err := commonFakeData(&r) - return &r, err -} - func (d *DummyService) UpdateValidatorDashboardArchiving(dashboardId t.VDBIdPrimary, archived bool) (*t.VDBPostArchivingReturnData, error) { r := t.VDBPostArchivingReturnData{} err := commonFakeData(&r) diff --git a/backend/pkg/api/data_access/user.go b/backend/pkg/api/data_access/user.go index 6babe686a..6da77a836 100644 --- a/backend/pkg/api/data_access/user.go +++ b/backend/pkg/api/data_access/user.go @@ -435,7 +435,7 @@ func (d *DataAccessService) GetProductSummary() (*t.ProductSummary, error) { } func (d *DataAccessService) GetUserDashboards(userId uint64) (*t.UserDashboardsData, error) { - // TODO @DATA-ACCESS Adjust to api changes: return ValidatorDashboard Archived + // TODO @DATA-ACCESS Adjust to api changes: return archival related fields result := &t.UserDashboardsData{} dbReturn := []struct { diff --git a/backend/pkg/api/data_access/vdb_helpers.go b/backend/pkg/api/data_access/vdb_helpers.go index 59863f328..ee6f91e11 100644 --- a/backend/pkg/api/data_access/vdb_helpers.go +++ b/backend/pkg/api/data_access/vdb_helpers.go @@ -16,7 +16,6 @@ type ValidatorDashboardRepository interface { CreateValidatorDashboard(userId uint64, name string, network uint64) (*t.VDBPostReturnData, error) RemoveValidatorDashboard(dashboardId t.VDBIdPrimary) error - GetValidatorDashboardArchiving(dashboardId t.VDBIdPrimary) (*t.VDBArchivedData, error) UpdateValidatorDashboardArchiving(dashboardId t.VDBIdPrimary, archived bool) (*t.VDBPostArchivingReturnData, error) UpdateValidatorDashboardName(dashboardId t.VDBIdPrimary, name string) (*t.VDBPostReturnData, error) diff --git a/backend/pkg/api/data_access/vdb_management.go b/backend/pkg/api/data_access/vdb_management.go index 3e8ca0380..a8d61700f 100644 --- a/backend/pkg/api/data_access/vdb_management.go +++ b/backend/pkg/api/data_access/vdb_management.go @@ -180,11 +180,6 @@ func (d *DataAccessService) RemoveValidatorDashboard(dashboardId t.VDBIdPrimary) return nil } -func (d *DataAccessService) GetValidatorDashboardArchiving(dashboardId t.VDBIdPrimary) (*t.VDBArchivedData, error) { - // TODO @DATA-ACCESS - return d.dummy.GetValidatorDashboardArchiving(dashboardId) -} - func (d *DataAccessService) UpdateValidatorDashboardArchiving(dashboardId t.VDBIdPrimary, archived bool) (*t.VDBPostArchivingReturnData, error) { // TODO @DATA-ACCESS return d.dummy.UpdateValidatorDashboardArchiving(dashboardId, archived) diff --git a/backend/pkg/api/handlers/internal.go b/backend/pkg/api/handlers/internal.go index 4c5e84f80..ea1a62b27 100644 --- a/backend/pkg/api/handlers/internal.go +++ b/backend/pkg/api/handlers/internal.go @@ -276,24 +276,6 @@ func (h *HandlerService) InternalDeleteValidatorDashboard(w http.ResponseWriter, returnNoContent(w) } -func (h *HandlerService) InternalGetValidatorDashboardArchiving(w http.ResponseWriter, r *http.Request) { - var v validationError - dashboardId := v.checkPrimaryDashboardId(mux.Vars(r)["dashboard_id"]) - if v.hasErrors() { - handleErr(w, v) - return - } - data, err := h.dai.GetValidatorDashboardArchiving(dashboardId) - if err != nil { - handleErr(w, err) - return - } - response := types.InternalGetValidatorDashboardArchivingResponse{ - Data: *data, - } - returnOk(w, response) -} - func (h *HandlerService) InternalPutValidatorDashboardArchiving(w http.ResponseWriter, r *http.Request) { var v validationError dashboardId := v.checkPrimaryDashboardId(mux.Vars(r)["dashboard_id"]) diff --git a/backend/pkg/api/handlers/public.go b/backend/pkg/api/handlers/public.go index 8be409bcf..1aef484d1 100644 --- a/backend/pkg/api/handlers/public.go +++ b/backend/pkg/api/handlers/public.go @@ -111,10 +111,6 @@ func (h *HandlerService) PublicDeleteValidatorDashboard(w http.ResponseWriter, r returnNoContent(w) } -func (h *HandlerService) PublicGetValidatorDashboardArchiving(w http.ResponseWriter, r *http.Request) { - returnNoContent(w) -} - func (h *HandlerService) PublicPutValidatorDashboardArchiving(w http.ResponseWriter, r *http.Request) { returnNoContent(w) } diff --git a/backend/pkg/api/router.go b/backend/pkg/api/router.go index 141c45d35..d8d44afc1 100644 --- a/backend/pkg/api/router.go +++ b/backend/pkg/api/router.go @@ -225,7 +225,6 @@ func addValidatorDashboardRoutes(hs *handlers.HandlerService, publicRouter, inte endpoints := []endpoint{ {http.MethodGet, "/{dashboard_id}", hs.PublicGetValidatorDashboard, hs.InternalGetValidatorDashboard}, {http.MethodDelete, "/{dashboard_id}", hs.PublicDeleteValidatorDashboard, hs.InternalDeleteValidatorDashboard}, - {http.MethodGet, "/{dashboard_id}/archiving", hs.PublicGetValidatorDashboardArchiving, hs.InternalGetValidatorDashboardArchiving}, {http.MethodPut, "/{dashboard_id}/archiving", hs.PublicPutValidatorDashboardArchiving, hs.InternalPutValidatorDashboardArchiving}, {http.MethodPut, "/{dashboard_id}/name", nil, hs.InternalPutValidatorDashboardName}, {http.MethodPost, "/{dashboard_id}/groups", hs.PublicPostValidatorDashboardGroups, hs.InternalPostValidatorDashboardGroups}, diff --git a/backend/pkg/api/types/dashboard.go b/backend/pkg/api/types/dashboard.go index 7ff5046e9..783b7fac7 100644 --- a/backend/pkg/api/types/dashboard.go +++ b/backend/pkg/api/types/dashboard.go @@ -5,10 +5,13 @@ type AccountDashboard struct { Name string `json:"name"` } type ValidatorDashboard struct { - Id uint64 `json:"id"` - Name string `json:"name"` - Archived bool `json:"archived"` - PublicIds []VDBPublicId `json:"public_ids,omitempty"` + Id uint64 `json:"id"` + Name string `json:"name"` + PublicIds []VDBPublicId `json:"public_ids,omitempty"` + Archived bool `json:"archived"` + ArchivedReason string `json:"archived_reason,omitempty"` // dashboard_limit, validator_limit, group_limit, none + ValidatorCount uint64 `json:"validator_count"` + GroupCount uint64 `json:"group_count"` } type UserDashboardsData struct { diff --git a/backend/pkg/api/types/validator_dashboard.go b/backend/pkg/api/types/validator_dashboard.go index 1beee1cc4..1ea804829 100644 --- a/backend/pkg/api/types/validator_dashboard.go +++ b/backend/pkg/api/types/validator_dashboard.go @@ -36,14 +36,6 @@ type VDBPostArchivingReturnData struct { Archived bool `json:"archived"` } -type VDBArchivedData struct { - Reason string `json:"reason"` // dashboard_limit, validator_limit, group_limit, none - ValidatorCount uint64 `json:"validator_count"` - GroupCount uint64 `json:"group_count"` -} - -type InternalGetValidatorDashboardArchivingResponse ApiDataResponse[VDBArchivedData] - // ------------------------------------------------------------ // Summary Tab diff --git a/frontend/types/api/dashboard.ts b/frontend/types/api/dashboard.ts index 793e6bf93..800998ebe 100644 --- a/frontend/types/api/dashboard.ts +++ b/frontend/types/api/dashboard.ts @@ -12,8 +12,11 @@ export interface AccountDashboard { export interface ValidatorDashboard { id: number /* uint64 */; name: string; - archived: boolean; public_ids?: VDBPublicId[]; + archived: boolean; + archived_reason?: string; // dashboard_limit, validator_limit, group_limit, none + validator_count: number /* uint64 */; + group_count: number /* uint64 */; } export interface UserDashboardsData { validator_dashboards: ValidatorDashboard[]; diff --git a/frontend/types/api/validator_dashboard.ts b/frontend/types/api/validator_dashboard.ts index ef4161b22..329843627 100644 --- a/frontend/types/api/validator_dashboard.ts +++ b/frontend/types/api/validator_dashboard.ts @@ -34,12 +34,6 @@ export interface VDBPostArchivingReturnData { id: number /* uint64 */; archived: boolean; } -export interface VDBArchivedData { - reason: string; // dashboard_limit, validator_limit, group_limit, none - validator_count: number /* uint64 */; - group_count: number /* uint64 */; -} -export type InternalGetValidatorDashboardArchivingResponse = ApiDataResponse; export interface VDBSummaryStatus { next_sync_count: number /* uint64 */; current_sync_count: number /* uint64 */; From a52be18835afadb2da6b5a45bd8a7ef201555f4a Mon Sep 17 00:00:00 2001 From: remoterami Date: Wed, 24 Jul 2024 16:47:54 +0200 Subject: [PATCH 04/15] basic return structs, endpoints and handlers added --- backend/pkg/api/data_access/block.go | 55 ++++++ backend/pkg/api/data_access/data_access.go | 2 + backend/pkg/api/data_access/dummy.go | 60 ++++++ backend/pkg/api/data_access/header.go | 5 + backend/pkg/api/handlers/common.go | 37 +++- backend/pkg/api/handlers/internal.go | 174 +++++++++++++++++ backend/pkg/api/router.go | 10 +- backend/pkg/api/types/block.go | 205 +++++++++++++++++++++ backend/pkg/api/types/common.go | 6 + 9 files changed, 546 insertions(+), 8 deletions(-) create mode 100644 backend/pkg/api/data_access/block.go create mode 100644 backend/pkg/api/types/block.go diff --git a/backend/pkg/api/data_access/block.go b/backend/pkg/api/data_access/block.go new file mode 100644 index 000000000..969d0bcdf --- /dev/null +++ b/backend/pkg/api/data_access/block.go @@ -0,0 +1,55 @@ +package dataaccess + +import ( + "context" + + t "github.com/gobitfly/beaconchain/pkg/api/types" +) + +type BlockRepository interface { + GetBlock(ctx context.Context, chainId, block uint64) (*t.BlockSummary, error) + GetBlockOverview(ctx context.Context, chainId, block uint64) (*t.BlockOverview, error) + GetBlockTransactions(ctx context.Context, chainId, block uint64) ([]t.BlockTransactionTableRow, error) + GetBlockVotes(ctx context.Context, chainId, block uint64) ([]t.BlockVoteTableRow, error) + GetBlockAttestations(ctx context.Context, chainId, block uint64) ([]t.BlockAttestationTableRow, error) + GetBlockWithdrawals(ctx context.Context, chainId, block uint64) ([]t.BlockWithdrawalTableRow, error) + GetBlockBlsChange(ctx context.Context, chainId, block uint64) ([]t.BlockBlsChangeTableRow, error) + GetBlockVoluntaryExits(ctx context.Context, chainId, block uint64) ([]t.BlockVoluntaryExitTableRow, error) + GetBlockBlobs(ctx context.Context, chainId, block uint64) ([]t.BlockBlobTableRow, error) +} + +func (d *DataAccessService) GetBlock(ctx context.Context, chainId, block uint64) (*t.BlockSummary, error) { + return d.dummy.GetBlock(ctx, chainId, block) +} + +func (d *DataAccessService) GetBlockOverview(ctx context.Context, chainId, block uint64) (*t.BlockOverview, error) { + return d.dummy.GetBlockOverview(ctx, chainId, block) +} + +func (d *DataAccessService) GetBlockTransactions(ctx context.Context, chainId, block uint64) ([]t.BlockTransactionTableRow, error) { + return d.dummy.GetBlockTransactions(ctx, chainId, block) +} + +func (d *DataAccessService) GetBlockVotes(ctx context.Context, chainId, block uint64) ([]t.BlockVoteTableRow, error) { + return d.dummy.GetBlockVotes(ctx, chainId, block) +} + +func (d *DataAccessService) GetBlockAttestations(ctx context.Context, chainId, block uint64) ([]t.BlockAttestationTableRow, error) { + return d.dummy.GetBlockAttestations(ctx, chainId, block) +} + +func (d *DataAccessService) GetBlockWithdrawals(ctx context.Context, chainId, block uint64) ([]t.BlockWithdrawalTableRow, error) { + return d.dummy.GetBlockWithdrawals(ctx, chainId, block) +} + +func (d *DataAccessService) GetBlockBlsChange(ctx context.Context, chainId, block uint64) ([]t.BlockBlsChangeTableRow, error) { + return d.dummy.GetBlockBlsChange(ctx, chainId, block) +} + +func (d *DataAccessService) GetBlockVoluntaryExits(ctx context.Context, chainId, block uint64) ([]t.BlockVoluntaryExitTableRow, error) { + return d.dummy.GetBlockVoluntaryExits(ctx, chainId, block) +} + +func (d *DataAccessService) GetBlockBlobs(ctx context.Context, chainId, block uint64) ([]t.BlockBlobTableRow, error) { + return d.dummy.GetBlockBlobs(ctx, chainId, block) +} diff --git a/backend/pkg/api/data_access/data_access.go b/backend/pkg/api/data_access/data_access.go index e04198870..de9a2c4a2 100644 --- a/backend/pkg/api/data_access/data_access.go +++ b/backend/pkg/api/data_access/data_access.go @@ -25,10 +25,12 @@ type DataAccessor interface { UserRepository NotificationsRepository AdminRepository + BlockRepository Close() GetLatestSlot() (uint64, error) + GetLatestBlock() (uint64, error) GetLatestExchangeRates() ([]t.EthConversionRate, error) GetProductSummary(ctx context.Context) (*t.ProductSummary, error) diff --git a/backend/pkg/api/data_access/dummy.go b/backend/pkg/api/data_access/dummy.go index 380d132d2..94fa68213 100644 --- a/backend/pkg/api/data_access/dummy.go +++ b/backend/pkg/api/data_access/dummy.go @@ -63,6 +63,12 @@ func (d *DummyService) GetLatestSlot() (uint64, error) { return r, err } +func (d *DummyService) GetLatestBlock() (uint64, error) { + r := uint64(0) + err := commonFakeData(&r) + return r, err +} + func (d *DummyService) GetLatestExchangeRates() ([]t.EthConversionRate, error) { r := []t.EthConversionRate{} err := commonFakeData(&r) @@ -618,3 +624,57 @@ func (d *DummyService) UpdateAdConfiguration(ctx context.Context, key, jquerySel func (d *DummyService) RemoveAdConfiguration(ctx context.Context, key string) error { return nil } + +func (d *DummyService) GetBlock(ctx context.Context, chainId, block uint64) (*t.BlockSummary, error) { + r := t.BlockSummary{} + err := commonFakeData(&r) + return &r, err +} + +func (d *DummyService) GetBlockOverview(ctx context.Context, chainId, block uint64) (*t.BlockOverview, error) { + r := t.BlockOverview{} + err := commonFakeData(&r) + return &r, err +} + +func (d *DummyService) GetBlockTransactions(ctx context.Context, chainId, block uint64) ([]t.BlockTransactionTableRow, error) { + r := []t.BlockTransactionTableRow{} + err := commonFakeData(&r) + return r, err +} + +func (d *DummyService) GetBlockVotes(ctx context.Context, chainId, block uint64) ([]t.BlockVoteTableRow, error) { + r := []t.BlockVoteTableRow{} + err := commonFakeData(&r) + return r, err +} + +func (d *DummyService) GetBlockAttestations(ctx context.Context, chainId, block uint64) ([]t.BlockAttestationTableRow, error) { + r := []t.BlockAttestationTableRow{} + err := commonFakeData(&r) + return r, err +} + +func (d *DummyService) GetBlockWithdrawals(ctx context.Context, chainId, block uint64) ([]t.BlockWithdrawalTableRow, error) { + r := []t.BlockWithdrawalTableRow{} + err := commonFakeData(&r) + return r, err +} + +func (d *DummyService) GetBlockBlsChange(ctx context.Context, chainId, block uint64) ([]t.BlockBlsChangeTableRow, error) { + r := []t.BlockBlsChangeTableRow{} + err := commonFakeData(&r) + return r, err +} + +func (d *DummyService) GetBlockVoluntaryExits(ctx context.Context, chainId, block uint64) ([]t.BlockVoluntaryExitTableRow, error) { + r := []t.BlockVoluntaryExitTableRow{} + err := commonFakeData(&r) + return r, err +} + +func (d *DummyService) GetBlockBlobs(ctx context.Context, chainId, block uint64) ([]t.BlockBlobTableRow, error) { + r := []t.BlockBlobTableRow{} + err := commonFakeData(&r) + return r, err +} diff --git a/backend/pkg/api/data_access/header.go b/backend/pkg/api/data_access/header.go index 928e96467..54627825d 100644 --- a/backend/pkg/api/data_access/header.go +++ b/backend/pkg/api/data_access/header.go @@ -11,6 +11,11 @@ func (d *DataAccessService) GetLatestSlot() (uint64, error) { return latestSlot, nil } +func (d *DataAccessService) GetLatestBlock() (uint64, error) { + // @DATA-ACCESS implement + return d.dummy.GetLatestBlock() +} + func (d *DataAccessService) GetLatestExchangeRates() ([]t.EthConversionRate, error) { result := []t.EthConversionRate{} diff --git a/backend/pkg/api/handlers/common.go b/backend/pkg/api/handlers/common.go index 16d3ce740..39f2340e8 100644 --- a/backend/pkg/api/handlers/common.go +++ b/backend/pkg/api/handlers/common.go @@ -359,6 +359,31 @@ func (h *HandlerService) getDashboardPremiumPerks(ctx context.Context, id types. return &userInfo.PremiumPerks, nil } +// helper function to unify handling of block detail request validation +func (h *HandlerService) validateBlockRequest(r *http.Request) (uint64, uint64, error) { + var v validationError + req := struct { + Network intOrString `json:"network"` + Block string `json:"block"` + }{} + if err := v.checkBody(&req, r); err != nil { + return 0, 0, err + } + chainId := v.checkNetwork(req.Network) + block, err := h.dai.GetLatestBlock() + if err != nil { + return 0, 0, err + } + if req.Block != "latest" { + block = v.checkUintMinMax(req.Block, 0, block, "block") + } + if v.hasErrors() { + return 0, 0, v + } + + return chainId, block, nil +} + // checkGroupId validates the given group id and returns it as an int64. // If the given group id is empty and allowEmpty is true, it returns -1 (all groups). func (v *validationError) checkGroupId(param string, allowEmpty bool) int64 { @@ -416,6 +441,10 @@ func checkMinMax[T number](v *validationError, param T, min T, max T, paramName return param } +func (v *validationError) checkUintMinMax(param string, min uint64, max uint64, paramName string) uint64 { + return checkMinMax(v, v.checkUint(param, paramName), min, max, paramName) +} + func (v *validationError) checkPagingParams(q url.Values) Paging { paging := Paging{ cursor: q.Get("cursor"), @@ -424,13 +453,7 @@ func (v *validationError) checkPagingParams(q url.Values) Paging { } if limitStr := q.Get("limit"); limitStr != "" { - limit, err := strconv.ParseUint(limitStr, 10, 64) - if err != nil { - v.add("limit", fmt.Sprintf("given value '%s' is not a valid positive integer", limitStr)) - return paging - } - checkMinMax(v, limit, 1, maxQueryLimit, "limit") - paging.limit = limit + paging.limit = v.checkUintMinMax(limitStr, 1, maxQueryLimit, "limit") } if paging.cursor != "" { diff --git a/backend/pkg/api/handlers/internal.go b/backend/pkg/api/handlers/internal.go index 318ca2650..302b679f4 100644 --- a/backend/pkg/api/handlers/internal.go +++ b/backend/pkg/api/handlers/internal.go @@ -1898,3 +1898,177 @@ func (h *HandlerService) InternalPostUserNotificationsTestWebhook(w http.Respons // TODO returnOk(w, nil) } + +// -------------------------------------- +// Blocks + +func (h *HandlerService) InternalGetBlock(w http.ResponseWriter, r *http.Request) { + chainId, block, err := h.validateBlockRequest(r) + if err != nil { + handleErr(w, err) + return + } + + data, err := h.dai.GetBlock(r.Context(), chainId, block) + if err != nil { + handleErr(w, err) + return + } + + response := types.InternalGetBlockResponse{ + Data: *data, + } + returnOk(w, response) +} + +func (h *HandlerService) InternalGetBlockOverview(w http.ResponseWriter, r *http.Request) { + chainId, block, err := h.validateBlockRequest(r) + if err != nil { + handleErr(w, err) + return + } + + data, err := h.dai.GetBlockOverview(r.Context(), chainId, block) + if err != nil { + handleErr(w, err) + return + } + response := types.InternalGetBlockOverviewResponse{ + Data: *data, + } + returnOk(w, response) +} + +func (h *HandlerService) InternalGetBlockTransactions(w http.ResponseWriter, r *http.Request) { + chainId, block, err := h.validateBlockRequest(r) + if err != nil { + handleErr(w, err) + return + } + + data, err := h.dai.GetBlockTransactions(r.Context(), chainId, block) + if err != nil { + handleErr(w, err) + return + } + + response := types.InternalGetBlockTransactionsResponse{ + Data: data, + } + returnOk(w, response) +} + +// WIP FROM HERE +func (h *HandlerService) InternalGetBlockVotes(w http.ResponseWriter, r *http.Request) { + chainId, block, err := h.validateBlockRequest(r) + if err != nil { + handleErr(w, err) + return + } + + data, err := h.dai.GetBlockVotes(r.Context(), chainId, block) + if err != nil { + handleErr(w, err) + return + } + + response := types.InternalGetBlockVotesResponse{ + Data: data, + } + returnOk(w, response) +} + +func (h *HandlerService) InternalGetBlockAttestations(w http.ResponseWriter, r *http.Request) { + chainId, block, err := h.validateBlockRequest(r) + if err != nil { + handleErr(w, err) + return + } + + data, err := h.dai.GetBlockAttestations(r.Context(), chainId, block) + if err != nil { + handleErr(w, err) + return + } + + response := types.InternalGetBlockAttestationsResponse{ + Data: data, + } + returnOk(w, response) +} + +func (h *HandlerService) InternalGetBlockWithdrawals(w http.ResponseWriter, r *http.Request) { + chainId, block, err := h.validateBlockRequest(r) + if err != nil { + handleErr(w, err) + return + } + + data, err := h.dai.GetBlockWithdrawals(r.Context(), chainId, block) + if err != nil { + handleErr(w, err) + return + } + + response := types.InternalGetBlockWtihdrawalsResponse{ + Data: data, + } + returnOk(w, response) +} + +func (h *HandlerService) InternalGetBlockBlsChange(w http.ResponseWriter, r *http.Request) { + chainId, block, err := h.validateBlockRequest(r) + if err != nil { + handleErr(w, err) + return + } + + data, err := h.dai.GetBlockBlsChange(r.Context(), chainId, block) + if err != nil { + handleErr(w, err) + return + } + + response := types.InternalGetBlockBlsChangeResponse{ + Data: data, + } + returnOk(w, response) +} + +func (h *HandlerService) InternalGetBlockVoluntaryExits(w http.ResponseWriter, r *http.Request) { + chainId, block, err := h.validateBlockRequest(r) + if err != nil { + handleErr(w, err) + return + } + + data, err := h.dai.GetBlockVoluntaryExits(r.Context(), chainId, block) + if err != nil { + handleErr(w, err) + return + } + + response := types.InternalGetBlockVoluntaryExitsResponse{ + Data: data, + } + returnOk(w, response) +} + +func (h *HandlerService) InternalGetBlockBlobs(w http.ResponseWriter, r *http.Request) { + chainId, block, err := h.validateBlockRequest(r) + if err != nil { + handleErr(w, err) + return + } + + data, err := h.dai.GetBlockBlobs(r.Context(), chainId, block) + if err != nil { + handleErr(w, err) + return + } + + response := types.InternalGetBlockBlobsResponse{ + Data: data, + } + returnOk(w, response) +} diff --git a/backend/pkg/api/router.go b/backend/pkg/api/router.go index 29f362c22..58ecd589e 100644 --- a/backend/pkg/api/router.go +++ b/backend/pkg/api/router.go @@ -138,7 +138,15 @@ func addRoutes(hs *handlers.HandlerService, publicRouter, internalRouter *mux.Ro {http.MethodGet, "/networks/{network}/epochs/{epoch}", hs.PublicGetNetworkEpoch, nil}, {http.MethodGet, "/networks/{network}/blocks", hs.PublicGetNetworkBlocks, nil}, - {http.MethodGet, "/networks/{network}/blocks/{block}", hs.PublicGetNetworkBlock, nil}, + {http.MethodGet, "/networks/{network}/blocks/{block}", hs.PublicGetNetworkBlock, hs.InternalGetBlock}, + {http.MethodGet, "/networks/{network}/blocks/{block}/overview", hs.PublicGetNetworkBlock, hs.InternalGetBlockOverview}, + {http.MethodGet, "/networks/{network}/blocks/{block}/transactions", hs.PublicGetNetworkBlock, hs.InternalGetBlockTransactions}, + {http.MethodGet, "/networks/{network}/blocks/{block}/votes", hs.PublicGetNetworkBlock, hs.InternalGetBlockVotes}, + {http.MethodGet, "/networks/{network}/blocks/{block}/attestations", hs.PublicGetNetworkBlock, hs.InternalGetBlockAttestations}, + {http.MethodGet, "/networks/{network}/blocks/{block}/withdrawals", hs.PublicGetNetworkBlock, hs.InternalGetBlockWithdrawals}, + {http.MethodGet, "/networks/{network}/blocks/{block}/bls-change", hs.PublicGetNetworkBlock, hs.InternalGetBlockBlsChange}, + {http.MethodGet, "/networks/{network}/blocks/{block}/voluntary-exits", hs.PublicGetNetworkBlock, hs.InternalGetBlockVoluntaryExits}, + {http.MethodGet, "/networks/{network}/blocks/{block}/blobs", hs.PublicGetNetworkBlock, hs.InternalGetBlockBlobs}, {http.MethodGet, "/networks/{network}/slots", hs.PublicGetNetworkSlots, nil}, {http.MethodGet, "/networks/{network}/slots/{slot}", hs.PublicGetNetworkSlot, nil}, {http.MethodGet, "/networks/{network}/validators/{validator}/blocks", hs.PublicGetNetworkValidatorBlocks, nil}, diff --git a/backend/pkg/api/types/block.go b/backend/pkg/api/types/block.go new file mode 100644 index 000000000..5b9a3096b --- /dev/null +++ b/backend/pkg/api/types/block.go @@ -0,0 +1,205 @@ +package types + +import ( + "github.com/shopspring/decimal" +) + +// count indicator per block details tab; each tab is only present if count > 0 +type BlockSummary struct { + Transactions uint64 `json:"transactions"` + Votes uint64 `json:"votes"` + Attestations uint64 `json:"attestations"` + Withdrawals uint64 `json:"withdrawals"` + BlsChanges uint64 `json:"bls_changes"` + VoluntaryExits uint64 `json:"voluntary_exits"` + Blobs uint64 `json:"blobs"` +} + +type InternalGetBlockResponse ApiDataResponse[BlockSummary] + +type BlockMevTag struct { + Name string `json:"name"` + Color string `json:"color"` +} + +type BlockExecutionPayload struct { + Block uint64 `json:"block"` + BlockHash Hash `json:"block_hash"` + ParentHash Hash `json:"parent_hash"` + PriorityFeesRecipient Address `json:"priority_fees_recipient"` + PriorityFees decimal.Decimal `json:"priority_fees"` + GasUsed uint64 `json:"gas_used"` + GasLimit uint64 `json:"gas_limit"` + BaseFeePerGas decimal.Decimal `json:"base_fee_per_gas"` + BaseFees decimal.Decimal `json:"base_fees"` + Transactions struct { + General uint64 `json:"general"` + Blob uint64 `json:"blob"` + } `json:"transactions"` + Time int64 `json:"time"` + ExtraData string `json:"extra_data,omitempty"` + Graffiti string `json:"graffiti"` +} + +type BlockConsensusLayer struct { + StateRoot Hash `json:"state_root"` + Signature Hash `json:"signature"` + RandaoReveal Hash `json:"randao_reveal"` + Attestations uint64 `json:"attestations"` + Votes uint64 `json:"votes"` + VotingValidators uint64 `json:"voting_validators"` + VoluntaryExits uint64 `json:"voluntary_exits"` + AttesterSlashings uint64 `json:"attester_slashings"` + ProposerSlashings uint64 `json:"proposer_slashings"` + Deposits uint64 `json:"deposit"` + SyncCommittee BlockSyncCommittee `json:"sync_committee"` + Eth1Data BlockEth1Data `json:"eth1_data"` +} + +type BlockSyncCommittee struct { + Participation float64 `json:"participation"` + Bits []bool `json:"bits"` + SyncCommittee []uint64 `json:"sync_committee"` + Signature Hash `json:"signature"` +} + +type BlockEth1Data struct { + BlockHash Hash `json:"block_hash"` + DepositCount uint64 `json:"deposit_count"` + DepositRoot Hash `json:"deposit_root"` +} + +type BlobInfo struct { + Count uint64 `json:"name"` + TxCount uint64 `json:"tx_count"` + GasUsed uint64 `json:"gas_used"` + GasPrice *decimal.Decimal `json:"gas_price"` + ExcessGas uint64 `json:"excess_gas"` + BurnedFees *decimal.Decimal `json:"burned_fees"` +} + +type BlockOverview struct { + // General + Block uint64 `json:"block"` + Time int64 `json:"time"` + + // Old blocks only + Miner *Address `json:"miner,omitempty"` + Rewards *decimal.Decimal `json:"rewards,omitempty"` + TxFees *decimal.Decimal `json:"tx_fees,omitempty"` + GasUsage *decimal.Decimal `json:"gas_usage,omitempty"` + GasLimit *struct { + Value uint64 `json:"value"` + Percent float64 `json:"percent"` + } `json:"gas_limit,omitempty"` + LowestGasPrice *decimal.Decimal `json:"lowest_gas_price,omitempty"` + Difficulty *decimal.Decimal `json:"difficulty,omitempty"` + // base + burned fee only present post EIP-1559 + BaseFee *decimal.Decimal `json:"base_fee,omitempty"` + BurnedFees *decimal.Decimal `json:"burned_fees,omitempty"` + Extra string `json:"extra,omitempty"` + Hash Hash `json:"hash,omitempty"` + ParentHash Hash `json:"parent_hash,omitempty"` + + // New blocks only + MevTags []BlockMevTag `json:"mev_tags,omitempty"` + Epoch uint64 `json:"epoch,omitempty"` + Slot uint64 `json:"slot,omitempty"` + Proposer uint64 `json:"proposer,omitempty"` + ProposerReward *ClElValue[decimal.Decimal] `json:"proposer_reward,omitempty"` + ProposerRewardRecipient *Address `json:"proposer_reward_recipient,omitempty"` + Status *struct { + Proposal string `json:"proposal"` // proposed, orphaned, missed, scheduled + Finalized string `json:"finalized"` // finalized, justified, not_finalized + } `json:"status,omitempty"` + PriorityFees *decimal.Decimal `json:"priority_fees,omitempty"` + Transactions *struct { + General uint64 `json:"general"` + Internal uint64 `json:"internal"` + Blob uint64 `json:"blob"` + } `json:"transactions,omitempty"` + BlockRoot Hash `json:"block_root,omitempty"` + ParentRoot Hash `json:"parent_root,omitempty"` + + ExecutionPayload *BlockExecutionPayload `json:"execution_payload,omitempty"` + ConsensusLayer *BlockConsensusLayer `json:"consensus_layer,omitempty"` +} + +type InternalGetBlockOverviewResponse ApiDataResponse[BlockOverview] + +type BlockTransactionTableRow struct { + Success bool `json:"success"` + TxHash Hash `json:"tx_hash"` + Method string `json:"method"` + Block uint64 `json:"block"` + Age uint64 `json:"age"` + From ContractAddress `json:"from"` + Type string `json:"type"` // in, out, self, contract + To ContractAddress `json:"to"` + Value decimal.Decimal `json:"value"` + GasPrice decimal.Decimal `json:"gas_price"` + TxFee decimal.Decimal `json:"tx_fee"` +} + +type InternalGetBlockTransactionsResponse ApiDataResponse[[]BlockTransactionTableRow] + +type BlockVoteTableRow struct { + AllocatedSlot uint64 `json:"allocated_slot"` + Committee uint64 `json:"committee"` + IncludedInBlock uint64 `json:"included_in_block"` + Validators []uint64 `json:"validators"` +} + +type InternalGetBlockVotesResponse ApiDataResponse[[]BlockVoteTableRow] + +type EpochInfo struct { + Epoch uint64 `json:"epoch"` + BlockRoot Hash `json:"block_root"` +} + +type BlockAttestationTableRow struct { + Slot uint64 `json:"slot"` + CommitteeIndex uint64 `json:"committee_index"` + AggregationBits []bool `json:"aggregation_bits"` + Validators []uint64 `json:"validators"` + BeaconBlockRoot Hash `json:"beacon_block_root"` + Source EpochInfo `json:"source"` + Target EpochInfo `json:"target"` + Signature Hash `json:"signature"` +} + +type InternalGetBlockAttestationsResponse ApiDataResponse[[]BlockAttestationTableRow] + +type BlockWithdrawalTableRow struct { + // TODO +} + +type InternalGetBlockWtihdrawalsResponse ApiDataResponse[[]BlockWithdrawalTableRow] + +type BlockBlsChangeTableRow struct { + Index uint64 `json:"index"` + Signature Hash `json:"signature"` + BlsPubkey Hash `json:"bls_pubkey"` + NewWithdrawalAddress ContractAddress `json:"new_withdrawal_address"` +} + +type InternalGetBlockBlsChangeResponse ApiDataResponse[[]BlockBlsChangeTableRow] + +type BlockVoluntaryExitTableRow struct { + Validator uint64 `json:"validator"` + Signature Hash `json:"signature"` +} + +type InternalGetBlockVoluntaryExitsResponse ApiDataResponse[[]BlockVoluntaryExitTableRow] + +type BlockBlobTableRow struct { + VersionedHash Hash `json:"versioned_hash"` + Commitment Hash `json:"commitment"` + Proof Hash `json:"proof"` + Size uint64 `json:"size"` + TransactionHash Hash `json:"transaction_hash"` + Block uint64 `json:"block"` + Data []byte `json:"data"` +} + +type InternalGetBlockBlobsResponse ApiDataResponse[[]BlockBlobTableRow] diff --git a/backend/pkg/api/types/common.go b/backend/pkg/api/types/common.go index 5d6bb9864..6ff8ebacc 100644 --- a/backend/pkg/api/types/common.go +++ b/backend/pkg/api/types/common.go @@ -37,6 +37,12 @@ type Address struct { Hash Hash `json:"hash"` Ens string `json:"ens,omitempty"` } + +type ContractAddress struct { + Address + IsContract bool `json:"is_contract"` +} + type LuckItem struct { Percent float64 `json:"percent"` Expected time.Time `json:"expected"` From 4b6113462e7518d0fd5dd5b3578c96e2d9efaab5 Mon Sep 17 00:00:00 2001 From: remoterami Date: Thu, 25 Jul 2024 13:27:58 +0200 Subject: [PATCH 05/15] adjusted return structs, removed endpoint duplicates, added ts structs --- backend/pkg/api/data_access/block.go | 6 +- backend/pkg/api/data_access/dummy.go | 2 +- backend/pkg/api/handlers/internal.go | 6 +- backend/pkg/api/handlers/public.go | 4 + backend/pkg/api/router.go | 22 ++- backend/pkg/api/types/block.go | 38 +++--- backend/pkg/api/types/common.go | 5 - frontend/types/api/block.ts | 196 +++++++++++++++++++++++++++ 8 files changed, 236 insertions(+), 43 deletions(-) create mode 100644 frontend/types/api/block.ts diff --git a/backend/pkg/api/data_access/block.go b/backend/pkg/api/data_access/block.go index 969d0bcdf..dc5f1b8ff 100644 --- a/backend/pkg/api/data_access/block.go +++ b/backend/pkg/api/data_access/block.go @@ -13,7 +13,7 @@ type BlockRepository interface { GetBlockVotes(ctx context.Context, chainId, block uint64) ([]t.BlockVoteTableRow, error) GetBlockAttestations(ctx context.Context, chainId, block uint64) ([]t.BlockAttestationTableRow, error) GetBlockWithdrawals(ctx context.Context, chainId, block uint64) ([]t.BlockWithdrawalTableRow, error) - GetBlockBlsChange(ctx context.Context, chainId, block uint64) ([]t.BlockBlsChangeTableRow, error) + GetBlockBlsChanges(ctx context.Context, chainId, block uint64) ([]t.BlockBlsChangeTableRow, error) GetBlockVoluntaryExits(ctx context.Context, chainId, block uint64) ([]t.BlockVoluntaryExitTableRow, error) GetBlockBlobs(ctx context.Context, chainId, block uint64) ([]t.BlockBlobTableRow, error) } @@ -42,8 +42,8 @@ func (d *DataAccessService) GetBlockWithdrawals(ctx context.Context, chainId, bl return d.dummy.GetBlockWithdrawals(ctx, chainId, block) } -func (d *DataAccessService) GetBlockBlsChange(ctx context.Context, chainId, block uint64) ([]t.BlockBlsChangeTableRow, error) { - return d.dummy.GetBlockBlsChange(ctx, chainId, block) +func (d *DataAccessService) GetBlockBlsChanges(ctx context.Context, chainId, block uint64) ([]t.BlockBlsChangeTableRow, error) { + return d.dummy.GetBlockBlsChanges(ctx, chainId, block) } func (d *DataAccessService) GetBlockVoluntaryExits(ctx context.Context, chainId, block uint64) ([]t.BlockVoluntaryExitTableRow, error) { diff --git a/backend/pkg/api/data_access/dummy.go b/backend/pkg/api/data_access/dummy.go index 94fa68213..efa72b535 100644 --- a/backend/pkg/api/data_access/dummy.go +++ b/backend/pkg/api/data_access/dummy.go @@ -661,7 +661,7 @@ func (d *DummyService) GetBlockWithdrawals(ctx context.Context, chainId, block u return r, err } -func (d *DummyService) GetBlockBlsChange(ctx context.Context, chainId, block uint64) ([]t.BlockBlsChangeTableRow, error) { +func (d *DummyService) GetBlockBlsChanges(ctx context.Context, chainId, block uint64) ([]t.BlockBlsChangeTableRow, error) { r := []t.BlockBlsChangeTableRow{} err := commonFakeData(&r) return r, err diff --git a/backend/pkg/api/handlers/internal.go b/backend/pkg/api/handlers/internal.go index 302b679f4..c1d2b27f9 100644 --- a/backend/pkg/api/handlers/internal.go +++ b/backend/pkg/api/handlers/internal.go @@ -2016,20 +2016,20 @@ func (h *HandlerService) InternalGetBlockWithdrawals(w http.ResponseWriter, r *h returnOk(w, response) } -func (h *HandlerService) InternalGetBlockBlsChange(w http.ResponseWriter, r *http.Request) { +func (h *HandlerService) InternalGetBlockBlsChanges(w http.ResponseWriter, r *http.Request) { chainId, block, err := h.validateBlockRequest(r) if err != nil { handleErr(w, err) return } - data, err := h.dai.GetBlockBlsChange(r.Context(), chainId, block) + data, err := h.dai.GetBlockBlsChanges(r.Context(), chainId, block) if err != nil { handleErr(w, err) return } - response := types.InternalGetBlockBlsChangeResponse{ + response := types.InternalGetBlockBlsChangesResponse{ Data: data, } returnOk(w, response) diff --git a/backend/pkg/api/handlers/public.go b/backend/pkg/api/handlers/public.go index 2744f1e72..27de72d21 100644 --- a/backend/pkg/api/handlers/public.go +++ b/backend/pkg/api/handlers/public.go @@ -451,6 +451,10 @@ func (h *HandlerService) PublicGetNetworkBlockAttestations(w http.ResponseWriter returnOk(w, nil) } +func (h *HandlerService) PublicGetNetworkBlockVotes(w http.ResponseWriter, r *http.Request) { + returnOk(w, nil) +} + func (h *HandlerService) PublicGetNetworkAggregatedAttestations(w http.ResponseWriter, r *http.Request) { returnOk(w, nil) } diff --git a/backend/pkg/api/router.go b/backend/pkg/api/router.go index 58ecd589e..c485bb32c 100644 --- a/backend/pkg/api/router.go +++ b/backend/pkg/api/router.go @@ -138,15 +138,9 @@ func addRoutes(hs *handlers.HandlerService, publicRouter, internalRouter *mux.Ro {http.MethodGet, "/networks/{network}/epochs/{epoch}", hs.PublicGetNetworkEpoch, nil}, {http.MethodGet, "/networks/{network}/blocks", hs.PublicGetNetworkBlocks, nil}, - {http.MethodGet, "/networks/{network}/blocks/{block}", hs.PublicGetNetworkBlock, hs.InternalGetBlock}, + {http.MethodGet, "/networks/{network}/blocks/{block}", nil, hs.InternalGetBlock}, {http.MethodGet, "/networks/{network}/blocks/{block}/overview", hs.PublicGetNetworkBlock, hs.InternalGetBlockOverview}, - {http.MethodGet, "/networks/{network}/blocks/{block}/transactions", hs.PublicGetNetworkBlock, hs.InternalGetBlockTransactions}, - {http.MethodGet, "/networks/{network}/blocks/{block}/votes", hs.PublicGetNetworkBlock, hs.InternalGetBlockVotes}, - {http.MethodGet, "/networks/{network}/blocks/{block}/attestations", hs.PublicGetNetworkBlock, hs.InternalGetBlockAttestations}, - {http.MethodGet, "/networks/{network}/blocks/{block}/withdrawals", hs.PublicGetNetworkBlock, hs.InternalGetBlockWithdrawals}, - {http.MethodGet, "/networks/{network}/blocks/{block}/bls-change", hs.PublicGetNetworkBlock, hs.InternalGetBlockBlsChange}, - {http.MethodGet, "/networks/{network}/blocks/{block}/voluntary-exits", hs.PublicGetNetworkBlock, hs.InternalGetBlockVoluntaryExits}, - {http.MethodGet, "/networks/{network}/blocks/{block}/blobs", hs.PublicGetNetworkBlock, hs.InternalGetBlockBlobs}, + {http.MethodGet, "/networks/{network}/blocks/{block}/votes", hs.PublicGetNetworkBlockVotes, hs.InternalGetBlockVotes}, {http.MethodGet, "/networks/{network}/slots", hs.PublicGetNetworkSlots, nil}, {http.MethodGet, "/networks/{network}/slots/{slot}", hs.PublicGetNetworkSlot, nil}, {http.MethodGet, "/networks/{network}/validators/{validator}/blocks", hs.PublicGetNetworkValidatorBlocks, nil}, @@ -160,7 +154,7 @@ func addRoutes(hs *handlers.HandlerService, publicRouter, internalRouter *mux.Ro {http.MethodGet, "/networks/{network}/validators/{validator}/attestations", hs.PublicGetNetworkValidatorAttestations, nil}, {http.MethodGet, "/networks/{network}/epochs/{epoch}/attestations", hs.PublicGetNetworkEpochAttestations, nil}, {http.MethodGet, "/networks/{network}/slots/{slot}/attestations", hs.PublicGetNetworkSlotAttestations, nil}, - {http.MethodGet, "/networks/{network}/blocks/{block}/attestations", hs.PublicGetNetworkBlockAttestations, nil}, + {http.MethodGet, "/networks/{network}/blocks/{block}/attestations", hs.PublicGetNetworkBlockAttestations, hs.InternalGetBlockAttestations}, {http.MethodGet, "/networks/{network}/aggregated-attestations", hs.PublicGetNetworkAggregatedAttestations, nil}, {http.MethodGet, "/networks/{network}/ethstore/{day}", hs.PublicGetNetworkEthStore, nil}, @@ -177,14 +171,14 @@ func addRoutes(hs *handlers.HandlerService, publicRouter, internalRouter *mux.Ro {http.MethodGet, "/networks/{network}/withdrawals", hs.PublicGetNetworkWithdrawals, nil}, {http.MethodGet, "/networks/{network}/slots/{slot}/withdrawals", hs.PublicGetNetworkSlotWithdrawals, nil}, - {http.MethodGet, "/networks/{network}/blocks/{block}/withdrawals", hs.PublicGetNetworkBlockWithdrawals, nil}, + {http.MethodGet, "/networks/{network}/blocks/{block}/withdrawals", hs.PublicGetNetworkBlockWithdrawals, hs.InternalGetBlockWithdrawals}, {http.MethodGet, "/networks/{network}/validators/{validator}/withdrawals", hs.PublicGetNetworkValidatorWithdrawals, nil}, {http.MethodGet, "/networks/{network}/withdrawal-credentials/{credential}/withdrawals", hs.PublicGetNetworkWithdrawalCredentialWithdrawals, nil}, {http.MethodGet, "/networks/{network}/voluntary-exits", hs.PublicGetNetworkVoluntaryExits, nil}, {http.MethodGet, "/networks/{network}/epochs/{epoch}/voluntary-exits", hs.PublicGetNetworkEpochVoluntaryExits, nil}, {http.MethodGet, "/networks/{network}/slots/{slot}/voluntary-exits", hs.PublicGetNetworkSlotVoluntaryExits, nil}, - {http.MethodGet, "/networks/{network}/blocks/{block}/voluntary-exits", hs.PublicGetNetworkBlockVoluntaryExits, nil}, + {http.MethodGet, "/networks/{network}/blocks/{block}/voluntary-exits", hs.PublicGetNetworkBlockVoluntaryExits, hs.InternalGetBlockVoluntaryExits}, {http.MethodGet, "/networks/{network}/addresses/{address}/balance-history", hs.PublicGetNetworkAddressBalanceHistory, nil}, {http.MethodGet, "/networks/{network}/addresses/{address}/token-supply-history", hs.PublicGetNetworkAddressTokenSupplyHistory, nil}, @@ -194,13 +188,13 @@ func addRoutes(hs *handlers.HandlerService, publicRouter, internalRouter *mux.Ro {http.MethodGet, "/networks/{network}/transactions/{hash}", hs.PublicGetNetworkTransaction, nil}, {http.MethodGet, "/networks/{network}/addresses/{address}/transactions", hs.PublicGetNetworkAddressTransactions, nil}, {http.MethodGet, "/networks/{network}/slots/{slot}/transactions", hs.PublicGetNetworkSlotTransactions, nil}, - {http.MethodGet, "/networks/{network}/blocks/{block}/transactions", hs.PublicGetNetworkBlockTransactions, nil}, - {http.MethodGet, "/networks/{network}/blocks/{block}/blobs", hs.PublicGetNetworkBlockBlobs, nil}, + {http.MethodGet, "/networks/{network}/blocks/{block}/transactions", hs.PublicGetNetworkBlockTransactions, hs.InternalGetBlockTransactions}, + {http.MethodGet, "/networks/{network}/blocks/{block}/blobs", hs.PublicGetNetworkBlockBlobs, hs.InternalGetBlockBlobs}, {http.MethodGet, "/networks/{network}/handlerService-changes", hs.PublicGetNetworkBlsChanges, nil}, {http.MethodGet, "/networks/{network}/epochs/{epoch}/handlerService-changes", hs.PublicGetNetworkEpochBlsChanges, nil}, {http.MethodGet, "/networks/{network}/slots/{slot}/handlerService-changes", hs.PublicGetNetworkSlotBlsChanges, nil}, - {http.MethodGet, "/networks/{network}/blocks/{block}/handlerService-changes", hs.PublicGetNetworkBlockBlsChanges, nil}, + {http.MethodGet, "/networks/{network}/blocks/{block}/handlerService-changes", hs.PublicGetNetworkBlockBlsChanges, hs.InternalGetBlockBlsChanges}, {http.MethodGet, "/networks/{network}/validators/{validator}/handlerService-changes", hs.PublicGetNetworkValidatorBlsChanges, nil}, {http.MethodGet, "/networks/ethereum/addresses/{address}/ens", hs.PublicGetNetworkAddressEns, nil}, diff --git a/backend/pkg/api/types/block.go b/backend/pkg/api/types/block.go index 5b9a3096b..630f9e93f 100644 --- a/backend/pkg/api/types/block.go +++ b/backend/pkg/api/types/block.go @@ -17,11 +17,6 @@ type BlockSummary struct { type InternalGetBlockResponse ApiDataResponse[BlockSummary] -type BlockMevTag struct { - Name string `json:"name"` - Color string `json:"color"` -} - type BlockExecutionPayload struct { Block uint64 `json:"block"` BlockHash Hash `json:"block_hash"` @@ -102,15 +97,18 @@ type BlockOverview struct { ParentHash Hash `json:"parent_hash,omitempty"` // New blocks only - MevTags []BlockMevTag `json:"mev_tags,omitempty"` + MevTags []struct { + Name string `json:"name"` + Color string `json:"color"` + } `json:"mev_tags,omitempty"` Epoch uint64 `json:"epoch,omitempty"` Slot uint64 `json:"slot,omitempty"` Proposer uint64 `json:"proposer,omitempty"` ProposerReward *ClElValue[decimal.Decimal] `json:"proposer_reward,omitempty"` ProposerRewardRecipient *Address `json:"proposer_reward_recipient,omitempty"` Status *struct { - Proposal string `json:"proposal"` // proposed, orphaned, missed, scheduled - Finalized string `json:"finalized"` // finalized, justified, not_finalized + Proposal string `json:"proposal" tstype:"'proposed' | 'orphaned' | 'missed' | 'scheduled'" faker:"oneof: proposed, orphaned, missed, scheduled"` + Finalized string `json:"finalized" tstype:"'finalized' | 'justified' | 'not_finalized'" faker:"oneof: finalized, justified, not_finalized"` } `json:"status,omitempty"` PriorityFees *decimal.Decimal `json:"priority_fees,omitempty"` Transactions *struct { @@ -133,9 +131,9 @@ type BlockTransactionTableRow struct { Method string `json:"method"` Block uint64 `json:"block"` Age uint64 `json:"age"` - From ContractAddress `json:"from"` - Type string `json:"type"` // in, out, self, contract - To ContractAddress `json:"to"` + From Address `json:"from"` + Type string `json:"type" tstype:"'out' | 'in' | 'out_in' | 'self' | 'contract'" faker:"oneof: out, int, out_in, self, contract"` + To Address `json:"to"` Value decimal.Decimal `json:"value"` GasPrice decimal.Decimal `json:"gas_price"` TxFee decimal.Decimal `json:"tx_fee"` @@ -171,19 +169,25 @@ type BlockAttestationTableRow struct { type InternalGetBlockAttestationsResponse ApiDataResponse[[]BlockAttestationTableRow] type BlockWithdrawalTableRow struct { - // TODO + // no design present yet, TODO confirm this + Index uint64 `json:"index"` + Epoch uint64 `json:"epoch"` + Slot uint64 `json:"slot"` + Age uint64 `json:"age"` + Recipient Address `json:"recipient"` + Amount decimal.Decimal `json:"amount"` } type InternalGetBlockWtihdrawalsResponse ApiDataResponse[[]BlockWithdrawalTableRow] type BlockBlsChangeTableRow struct { - Index uint64 `json:"index"` - Signature Hash `json:"signature"` - BlsPubkey Hash `json:"bls_pubkey"` - NewWithdrawalAddress ContractAddress `json:"new_withdrawal_address"` + Index uint64 `json:"index"` + Signature Hash `json:"signature"` + BlsPubkey Hash `json:"bls_pubkey"` + NewWithdrawalAddress Address `json:"new_withdrawal_address"` } -type InternalGetBlockBlsChangeResponse ApiDataResponse[[]BlockBlsChangeTableRow] +type InternalGetBlockBlsChangesResponse ApiDataResponse[[]BlockBlsChangeTableRow] type BlockVoluntaryExitTableRow struct { Validator uint64 `json:"validator"` diff --git a/backend/pkg/api/types/common.go b/backend/pkg/api/types/common.go index 6ff8ebacc..05945e382 100644 --- a/backend/pkg/api/types/common.go +++ b/backend/pkg/api/types/common.go @@ -38,11 +38,6 @@ type Address struct { Ens string `json:"ens,omitempty"` } -type ContractAddress struct { - Address - IsContract bool `json:"is_contract"` -} - type LuckItem struct { Percent float64 `json:"percent"` Expected time.Time `json:"expected"` diff --git a/frontend/types/api/block.ts b/frontend/types/api/block.ts new file mode 100644 index 000000000..d3d5bf74d --- /dev/null +++ b/frontend/types/api/block.ts @@ -0,0 +1,196 @@ +// Code generated by tygo. DO NOT EDIT. +/* eslint-disable */ +import type { ApiDataResponse, Hash, Address, ClElValue } from './common' + +////////// +// source: block.go + +/** + * count indicator per block details tab; each tab is only present if count > 0 + */ +export interface BlockSummary { + transactions: number /* uint64 */; + votes: number /* uint64 */; + attestations: number /* uint64 */; + withdrawals: number /* uint64 */; + bls_changes: number /* uint64 */; + voluntary_exits: number /* uint64 */; + blobs: number /* uint64 */; +} +export type InternalGetBlockResponse = ApiDataResponse; +export interface BlockExecutionPayload { + block: number /* uint64 */; + block_hash: Hash; + parent_hash: Hash; + priority_fees_recipient: Address; + priority_fees: string /* decimal.Decimal */; + gas_used: number /* uint64 */; + gas_limit: number /* uint64 */; + base_fee_per_gas: string /* decimal.Decimal */; + base_fees: string /* decimal.Decimal */; + transactions: { + general: number /* uint64 */; + blob: number /* uint64 */; + }; + time: number /* int64 */; + extra_data?: string; + graffiti: string; +} +export interface BlockConsensusLayer { + state_root: Hash; + signature: Hash; + randao_reveal: Hash; + attestations: number /* uint64 */; + votes: number /* uint64 */; + voting_validators: number /* uint64 */; + voluntary_exits: number /* uint64 */; + attester_slashings: number /* uint64 */; + proposer_slashings: number /* uint64 */; + deposit: number /* uint64 */; + sync_committee: BlockSyncCommittee; + eth1_data: BlockEth1Data; +} +export interface BlockSyncCommittee { + participation: number /* float64 */; + bits: boolean[]; + sync_committee: number /* uint64 */[]; + signature: Hash; +} +export interface BlockEth1Data { + block_hash: Hash; + deposit_count: number /* uint64 */; + deposit_root: Hash; +} +export interface BlobInfo { + name: number /* uint64 */; + tx_count: number /* uint64 */; + gas_used: number /* uint64 */; + gas_price?: string /* decimal.Decimal */; + excess_gas: number /* uint64 */; + burned_fees?: string /* decimal.Decimal */; +} +export interface BlockOverview { + /** + * General + */ + block: number /* uint64 */; + time: number /* int64 */; + /** + * Old blocks only + */ + miner?: Address; + rewards?: string /* decimal.Decimal */; + tx_fees?: string /* decimal.Decimal */; + gas_usage?: string /* decimal.Decimal */; + gas_limit?: { + value: number /* uint64 */; + percent: number /* float64 */; + }; + lowest_gas_price?: string /* decimal.Decimal */; + difficulty?: string /* decimal.Decimal */; + /** + * base + burned fee only present post EIP-1559 + */ + base_fee?: string /* decimal.Decimal */; + burned_fees?: string /* decimal.Decimal */; + extra?: string; + hash?: Hash; + parent_hash?: Hash; + /** + * New blocks only + */ + mev_tags?: { + name: string; + color: string; + }[]; + epoch?: number /* uint64 */; + slot?: number /* uint64 */; + proposer?: number /* uint64 */; + proposer_reward?: ClElValue; + proposer_reward_recipient?: Address; + status?: { + proposal: 'proposed' | 'orphaned' | 'missed' | 'scheduled'; + finalized: 'finalized' | 'justified' | 'not_finalized'; + }; + priority_fees?: string /* decimal.Decimal */; + transactions?: { + general: number /* uint64 */; + internal: number /* uint64 */; + blob: number /* uint64 */; + }; + block_root?: Hash; + parent_root?: Hash; + execution_payload?: BlockExecutionPayload; + consensus_layer?: BlockConsensusLayer; +} +export type InternalGetBlockOverviewResponse = ApiDataResponse; +export interface BlockTransactionTableRow { + success: boolean; + tx_hash: Hash; + method: string; + block: number /* uint64 */; + age: number /* uint64 */; + from: Address; + type: 'out' | 'in' | 'out_in' | 'self' | 'contract'; + to: Address; + value: string /* decimal.Decimal */; + gas_price: string /* decimal.Decimal */; + tx_fee: string /* decimal.Decimal */; +} +export type InternalGetBlockTransactionsResponse = ApiDataResponse; +export interface BlockVoteTableRow { + allocated_slot: number /* uint64 */; + committee: number /* uint64 */; + included_in_block: number /* uint64 */; + validators: number /* uint64 */[]; +} +export type InternalGetBlockVotesResponse = ApiDataResponse; +export interface EpochInfo { + epoch: number /* uint64 */; + block_root: Hash; +} +export interface BlockAttestationTableRow { + slot: number /* uint64 */; + committee_index: number /* uint64 */; + aggregation_bits: boolean[]; + validators: number /* uint64 */[]; + beacon_block_root: Hash; + source: EpochInfo; + target: EpochInfo; + signature: Hash; +} +export type InternalGetBlockAttestationsResponse = ApiDataResponse; +export interface BlockWithdrawalTableRow { + /** + * no design present yet, TODO confirm this + */ + index: number /* uint64 */; + epoch: number /* uint64 */; + slot: number /* uint64 */; + age: number /* uint64 */; + recipient: Address; + amount: string /* decimal.Decimal */; +} +export type InternalGetBlockWtihdrawalsResponse = ApiDataResponse; +export interface BlockBlsChangeTableRow { + index: number /* uint64 */; + signature: Hash; + bls_pubkey: Hash; + new_withdrawal_address: Address; +} +export type InternalGetBlockBlsChangesResponse = ApiDataResponse; +export interface BlockVoluntaryExitTableRow { + validator: number /* uint64 */; + signature: Hash; +} +export type InternalGetBlockVoluntaryExitsResponse = ApiDataResponse; +export interface BlockBlobTableRow { + versioned_hash: Hash; + commitment: Hash; + proof: Hash; + size: number /* uint64 */; + transaction_hash: Hash; + block: number /* uint64 */; + data: string; +} +export type InternalGetBlockBlobsResponse = ApiDataResponse; From c8f61850d10c09b54543ac2b9a48d7277ff67afa Mon Sep 17 00:00:00 2001 From: remoterami Date: Mon, 29 Jul 2024 12:11:43 +0200 Subject: [PATCH 06/15] comments adjusted --- backend/pkg/api/data_access/block.go | 9 +++++++++ backend/pkg/api/handlers/internal.go | 1 - backend/pkg/api/types/block.go | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/backend/pkg/api/data_access/block.go b/backend/pkg/api/data_access/block.go index dc5f1b8ff..9a5c17f32 100644 --- a/backend/pkg/api/data_access/block.go +++ b/backend/pkg/api/data_access/block.go @@ -19,37 +19,46 @@ type BlockRepository interface { } func (d *DataAccessService) GetBlock(ctx context.Context, chainId, block uint64) (*t.BlockSummary, error) { + // @DATA-ACCESS return d.dummy.GetBlock(ctx, chainId, block) } func (d *DataAccessService) GetBlockOverview(ctx context.Context, chainId, block uint64) (*t.BlockOverview, error) { + // @DATA-ACCESS return d.dummy.GetBlockOverview(ctx, chainId, block) } func (d *DataAccessService) GetBlockTransactions(ctx context.Context, chainId, block uint64) ([]t.BlockTransactionTableRow, error) { + // @DATA-ACCESS return d.dummy.GetBlockTransactions(ctx, chainId, block) } func (d *DataAccessService) GetBlockVotes(ctx context.Context, chainId, block uint64) ([]t.BlockVoteTableRow, error) { + // @DATA-ACCESS return d.dummy.GetBlockVotes(ctx, chainId, block) } func (d *DataAccessService) GetBlockAttestations(ctx context.Context, chainId, block uint64) ([]t.BlockAttestationTableRow, error) { + // @DATA-ACCESS return d.dummy.GetBlockAttestations(ctx, chainId, block) } func (d *DataAccessService) GetBlockWithdrawals(ctx context.Context, chainId, block uint64) ([]t.BlockWithdrawalTableRow, error) { + // @DATA-ACCESS return d.dummy.GetBlockWithdrawals(ctx, chainId, block) } func (d *DataAccessService) GetBlockBlsChanges(ctx context.Context, chainId, block uint64) ([]t.BlockBlsChangeTableRow, error) { + // @DATA-ACCESS return d.dummy.GetBlockBlsChanges(ctx, chainId, block) } func (d *DataAccessService) GetBlockVoluntaryExits(ctx context.Context, chainId, block uint64) ([]t.BlockVoluntaryExitTableRow, error) { + // @DATA-ACCESS return d.dummy.GetBlockVoluntaryExits(ctx, chainId, block) } func (d *DataAccessService) GetBlockBlobs(ctx context.Context, chainId, block uint64) ([]t.BlockBlobTableRow, error) { + // @DATA-ACCESS return d.dummy.GetBlockBlobs(ctx, chainId, block) } diff --git a/backend/pkg/api/handlers/internal.go b/backend/pkg/api/handlers/internal.go index c1d2b27f9..ca883d670 100644 --- a/backend/pkg/api/handlers/internal.go +++ b/backend/pkg/api/handlers/internal.go @@ -1958,7 +1958,6 @@ func (h *HandlerService) InternalGetBlockTransactions(w http.ResponseWriter, r * returnOk(w, response) } -// WIP FROM HERE func (h *HandlerService) InternalGetBlockVotes(w http.ResponseWriter, r *http.Request) { chainId, block, err := h.validateBlockRequest(r) if err != nil { diff --git a/backend/pkg/api/types/block.go b/backend/pkg/api/types/block.go index 630f9e93f..5b3d071c2 100644 --- a/backend/pkg/api/types/block.go +++ b/backend/pkg/api/types/block.go @@ -203,7 +203,7 @@ type BlockBlobTableRow struct { Size uint64 `json:"size"` TransactionHash Hash `json:"transaction_hash"` Block uint64 `json:"block"` - Data []byte `json:"data"` + Data string `json:"data"` } type InternalGetBlockBlobsResponse ApiDataResponse[[]BlockBlobTableRow] From b657c75125ee983938a455315fafa8256df55d23 Mon Sep 17 00:00:00 2001 From: remoterami Date: Mon, 29 Jul 2024 15:43:18 +0200 Subject: [PATCH 07/15] enforcing archival status --- backend/pkg/api/data_access/dummy.go | 11 +++- backend/pkg/api/data_access/user.go | 12 ++++- backend/pkg/api/handlers/auth.go | 14 ++++- backend/pkg/api/handlers/common.go | 26 ++++----- backend/pkg/api/handlers/internal.go | 56 ++++++++++++++++++-- backend/pkg/api/router.go | 14 +++-- backend/pkg/api/types/dashboard.go | 2 +- backend/pkg/api/types/validator_dashboard.go | 4 +- frontend/types/api/dashboard.ts | 2 +- frontend/types/api/validator_dashboard.ts | 2 +- 10 files changed, 115 insertions(+), 28 deletions(-) diff --git a/backend/pkg/api/data_access/dummy.go b/backend/pkg/api/data_access/dummy.go index 62434fed6..167b3f89d 100644 --- a/backend/pkg/api/data_access/dummy.go +++ b/backend/pkg/api/data_access/dummy.go @@ -483,7 +483,16 @@ func (d *DummyService) GetSearchValidatorsByGraffiti(ctx context.Context, chainI return &r, err } -func (d *DummyService) GetUserValidatorDashboardCount(ctx context.Context, userId uint64) (uint64, error) { +func (d *DummyService) GetUserValidatorDashboard(ctx context.Context, dashboardId t.VDBIdPrimary) (*t.ValidatorDashboard, error) { + r := t.ValidatorDashboard{} + // return semi-valid data to not break staging + //nolint:errcheck + commonFakeData(&r) + r.IsArchived = false + return &r, nil +} + +func (d *DummyService) GetUserValidatorDashboardCount(ctx context.Context, userId uint64, active bool) (uint64, error) { r := uint64(0) err := commonFakeData(&r) return r, err diff --git a/backend/pkg/api/data_access/user.go b/backend/pkg/api/data_access/user.go index 69775d856..9600c6915 100644 --- a/backend/pkg/api/data_access/user.go +++ b/backend/pkg/api/data_access/user.go @@ -27,7 +27,8 @@ type UserRepository interface { GetUserIdByConfirmationHash(hash string) (uint64, error) GetUserInfo(ctx context.Context, id uint64) (*t.UserInfo, error) GetUserDashboards(ctx context.Context, userId uint64) (*t.UserDashboardsData, error) - GetUserValidatorDashboardCount(ctx context.Context, userId uint64) (uint64, error) + GetUserValidatorDashboard(ctx context.Context, dashboardId t.VDBIdPrimary) (*t.ValidatorDashboard, error) + GetUserValidatorDashboardCount(ctx context.Context, userId uint64, active bool) (uint64, error) } func (d *DataAccessService) GetUserByEmail(ctx context.Context, email string) (uint64, error) { @@ -604,7 +605,14 @@ func (d *DataAccessService) GetUserDashboards(ctx context.Context, userId uint64 return result, nil } -func (d *DataAccessService) GetUserValidatorDashboardCount(ctx context.Context, userId uint64) (uint64, error) { +func (d *DataAccessService) GetUserValidatorDashboard(ctx context.Context, dashboardId t.VDBIdPrimary) (*t.ValidatorDashboard, error) { + // TODO @DATA-ACCESS + return d.dummy.GetUserValidatorDashboard(ctx, dashboardId) +} + +// return number of active / archived dashboards +func (d *DataAccessService) GetUserValidatorDashboardCount(ctx context.Context, userId uint64, active bool) (uint64, error) { + // @DATA-ACCESS return number of dashboards depending on archival status (see comment above) var count uint64 err := d.alloyReader.Get(&count, ` SELECT COUNT(*) FROM users_val_dashboards diff --git a/backend/pkg/api/handlers/auth.go b/backend/pkg/api/handlers/auth.go index 618ef557c..8558ed576 100644 --- a/backend/pkg/api/handlers/auth.go +++ b/backend/pkg/api/handlers/auth.go @@ -442,7 +442,7 @@ func (h *HandlerService) InternalPutUserPassword(w http.ResponseWriter, r *http. // returns a middleware that checks if user has access to dashboard when a primary id is used // expects a userIdFunc to return user id, probably GetUserIdBySession or GetUserIdByApiKey -func (h *HandlerService) GetVDBAuthMiddleware(userIdFunc func(r *http.Request) (uint64, error)) func(http.Handler) http.Handler { +func (h *HandlerService) GetVDBAuthMiddleware(userIdFunc func(r *http.Request) (uint64, error), rejectArchived bool) func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var err error @@ -476,6 +476,18 @@ func (h *HandlerService) GetVDBAuthMiddleware(userIdFunc func(r *http.Request) ( handleErr(w, newNotFoundErr("dashboard with id %v not found", dashboardId)) return } + if rejectArchived { + db, err := h.dai.GetUserValidatorDashboard(r.Context(), types.VDBIdPrimary(dashboardId)) + if err != nil { + handleErr(w, err) + return + } + if db.IsArchived { + // user does not have access to dashboard + handleErr(w, newConflictErr("dashboard with id %v is archived", dashboardId)) + return + } + } next.ServeHTTP(w, r) }) diff --git a/backend/pkg/api/handlers/common.go b/backend/pkg/api/handlers/common.go index 36817aab5..d55c27fdb 100644 --- a/backend/pkg/api/handlers/common.go +++ b/backend/pkg/api/handlers/common.go @@ -68,17 +68,18 @@ var ( ) const ( - maxNameLength = 50 - maxValidatorsInList = 20 - maxQueryLimit uint64 = 100 - defaultReturnLimit uint64 = 10 - sortOrderAscending = "asc" - sortOrderDescending = "desc" - defaultSortOrder = sortOrderAscending - ethereum = "ethereum" - gnosis = "gnosis" - allowEmpty = true - forbidEmpty = false + maxNameLength = 50 + maxValidatorsInList = 20 + maxQueryLimit uint64 = 100 + defaultReturnLimit uint64 = 10 + sortOrderAscending = "asc" + sortOrderDescending = "desc" + defaultSortOrder = sortOrderAscending + ethereum = "ethereum" + gnosis = "gnosis" + allowEmpty = true + forbidEmpty = false + maxArchivedDashboardsCount = 10 ) var ( @@ -297,7 +298,8 @@ func (h *HandlerService) getDashboardId(ctx context.Context, dashboardIdParam in } // handleDashboardId is a helper function to both validate the dashboard id param and convert it to a VDBId. -// it should be used as the last validation step for all internal dashboard handlers. +// it should be used as the last validation step for all internal dashboard GET-handlers. +// Modifying handlers (POST, PUT, DELETE) should only accept primary dashboard ids. func (h *HandlerService) handleDashboardId(ctx context.Context, param string) (*types.VDBId, error) { // validate dashboard id param dashboardIdParam, err := parseDashboardId(param) diff --git a/backend/pkg/api/handlers/internal.go b/backend/pkg/api/handlers/internal.go index e2f1ee534..1a75bf901 100644 --- a/backend/pkg/api/handlers/internal.go +++ b/backend/pkg/api/handlers/internal.go @@ -206,14 +206,13 @@ func (h *HandlerService) InternalPostValidatorDashboards(w http.ResponseWriter, handleErr(w, err) return } - dashboardCount, err := h.dai.GetUserValidatorDashboardCount(r.Context(), userId) + dashboardCount, err := h.dai.GetUserValidatorDashboardCount(r.Context(), userId, true) if err != nil { handleErr(w, err) return } if dashboardCount >= userInfo.PremiumPerks.ValidatorDasboards { returnConflict(w, errors.New("maximum number of validator dashboards reached")) - return } data, err := h.dai.CreateValidatorDashboard(r.Context(), userId, name, chainId) @@ -297,7 +296,7 @@ func (h *HandlerService) InternalPutValidatorDashboardArchiving(w http.ResponseW var v validationError dashboardId := v.checkPrimaryDashboardId(mux.Vars(r)["dashboard_id"]) req := struct { - Archived bool `json:"archived"` + IsArchived bool `json:"is_archived"` }{} if err := v.checkBody(&req, r); err != nil { handleErr(w, err) @@ -307,7 +306,56 @@ func (h *HandlerService) InternalPutValidatorDashboardArchiving(w http.ResponseW handleErr(w, v) return } - data, err := h.dai.UpdateValidatorDashboardArchiving(r.Context(), dashboardId, req.Archived) + + // check conditions for changing archival status + dashboardInfo, err := h.dai.GetUserValidatorDashboard(r.Context(), dashboardId) + if err != nil { + handleErr(w, err) + return + } + if dashboardInfo.IsArchived == req.IsArchived { + // nothing to do + returnOk(w, types.ApiDataResponse[types.VDBPostArchivingReturnData]{ + Data: types.VDBPostArchivingReturnData{Id: uint64(dashboardId), IsArchived: req.IsArchived}, + }) + } + + userId, ok := r.Context().Value(ctxUserIdKey).(uint64) + if !ok { + handleErr(w, errors.New("error getting user id from context")) + return + } + dashboardCount, err := h.dai.GetUserValidatorDashboardCount(r.Context(), userId, !req.IsArchived) + if err != nil { + handleErr(w, err) + return + } + if req.IsArchived { + if dashboardCount >= maxArchivedDashboardsCount { + returnConflict(w, errors.New("maximum number of archived validator dashboards reached")) + return + } + } else { + userInfo, err := h.dai.GetUserInfo(r.Context(), userId) + if err != nil { + handleErr(w, err) + return + } + if dashboardCount >= userInfo.PremiumPerks.ValidatorDasboards { + returnConflict(w, errors.New("maximum number of active validator dashboards reached")) + return + } + if dashboardInfo.GroupCount >= userInfo.PremiumPerks.ValidatorGroupsPerDashboard { + returnConflict(w, errors.New("maximum number of groups in dashboards reached")) + return + } + if dashboardInfo.ValidatorCount >= userInfo.PremiumPerks.ValidatorsPerDashboard { + returnConflict(w, errors.New("maximum number of validators in dashboards reached")) + return + } + } + + data, err := h.dai.UpdateValidatorDashboardArchiving(r.Context(), dashboardId, req.IsArchived) if err != nil { handleErr(w, err) return diff --git a/backend/pkg/api/router.go b/backend/pkg/api/router.go index 9c27e6e49..b23e70d99 100644 --- a/backend/pkg/api/router.go +++ b/backend/pkg/api/router.go @@ -222,16 +222,24 @@ func addValidatorDashboardRoutes(hs *handlers.HandlerService, publicRouter, inte publicDashboardRouter := publicRouter.PathPrefix(vdbPath).Subrouter() internalDashboardRouter := internalRouter.PathPrefix(vdbPath).Subrouter() + + // allow access to handle dashboard archiving + if !cfg.Frontend.Debug { + publicDashboardRouter.Use(hs.GetVDBAuthMiddleware(hs.GetUserIdByApiKey, false), hs.VDBPublicApiCheckMiddleware) + internalDashboardRouter.Use(hs.GetVDBAuthMiddleware(hs.GetUserIdBySession, false), GetAuthMiddleware(cfg.ApiKeySecret)) + } + publicDashboardRouter.HandleFunc("/{dashboard_id}/archiving", hs.PublicPutValidatorDashboardArchiving).Methods(http.MethodPut, http.MethodOptions) + internalDashboardRouter.HandleFunc("/{dashboard_id}/archiving", hs.InternalPutValidatorDashboardArchiving).Methods(http.MethodPut, http.MethodOptions) + // add middleware to check if user has access to dashboard if !cfg.Frontend.Debug { - publicDashboardRouter.Use(hs.GetVDBAuthMiddleware(hs.GetUserIdByApiKey), hs.VDBPublicApiCheckMiddleware) - internalDashboardRouter.Use(hs.GetVDBAuthMiddleware(hs.GetUserIdBySession), GetAuthMiddleware(cfg.ApiKeySecret)) + publicDashboardRouter.Use(hs.GetVDBAuthMiddleware(hs.GetUserIdByApiKey, true), hs.VDBPublicApiCheckMiddleware) + internalDashboardRouter.Use(hs.GetVDBAuthMiddleware(hs.GetUserIdBySession, true), GetAuthMiddleware(cfg.ApiKeySecret)) } endpoints := []endpoint{ {http.MethodGet, "/{dashboard_id}", hs.PublicGetValidatorDashboard, hs.InternalGetValidatorDashboard}, {http.MethodDelete, "/{dashboard_id}", hs.PublicDeleteValidatorDashboard, hs.InternalDeleteValidatorDashboard}, - {http.MethodPut, "/{dashboard_id}/archiving", hs.PublicPutValidatorDashboardArchiving, hs.InternalPutValidatorDashboardArchiving}, {http.MethodPut, "/{dashboard_id}/name", nil, hs.InternalPutValidatorDashboardName}, {http.MethodPost, "/{dashboard_id}/groups", hs.PublicPostValidatorDashboardGroups, hs.InternalPostValidatorDashboardGroups}, {http.MethodPut, "/{dashboard_id}/groups/{group_id}", hs.PublicPutValidatorDashboardGroups, hs.InternalPutValidatorDashboardGroups}, diff --git a/backend/pkg/api/types/dashboard.go b/backend/pkg/api/types/dashboard.go index 783b7fac7..ed903ac48 100644 --- a/backend/pkg/api/types/dashboard.go +++ b/backend/pkg/api/types/dashboard.go @@ -8,7 +8,7 @@ type ValidatorDashboard struct { Id uint64 `json:"id"` Name string `json:"name"` PublicIds []VDBPublicId `json:"public_ids,omitempty"` - Archived bool `json:"archived"` + IsArchived bool `json:"is_archived"` ArchivedReason string `json:"archived_reason,omitempty"` // dashboard_limit, validator_limit, group_limit, none ValidatorCount uint64 `json:"validator_count"` GroupCount uint64 `json:"group_count"` diff --git a/backend/pkg/api/types/validator_dashboard.go b/backend/pkg/api/types/validator_dashboard.go index c529e7d77..e0a9488cc 100644 --- a/backend/pkg/api/types/validator_dashboard.go +++ b/backend/pkg/api/types/validator_dashboard.go @@ -33,8 +33,8 @@ type VDBOverviewData struct { type InternalGetValidatorDashboardResponse ApiDataResponse[VDBOverviewData] type VDBPostArchivingReturnData struct { - Id uint64 `json:"id"` - Archived bool `json:"archived"` + Id uint64 `json:"id"` + IsArchived bool `json:"is_archived"` } // ------------------------------------------------------------ diff --git a/frontend/types/api/dashboard.ts b/frontend/types/api/dashboard.ts index 800998ebe..1b9900d3a 100644 --- a/frontend/types/api/dashboard.ts +++ b/frontend/types/api/dashboard.ts @@ -13,7 +13,7 @@ export interface ValidatorDashboard { id: number /* uint64 */; name: string; public_ids?: VDBPublicId[]; - archived: boolean; + is_archived: boolean; archived_reason?: string; // dashboard_limit, validator_limit, group_limit, none validator_count: number /* uint64 */; group_count: number /* uint64 */; diff --git a/frontend/types/api/validator_dashboard.ts b/frontend/types/api/validator_dashboard.ts index 6f7a1a0b5..a9fd6dcbf 100644 --- a/frontend/types/api/validator_dashboard.ts +++ b/frontend/types/api/validator_dashboard.ts @@ -33,7 +33,7 @@ export interface VDBOverviewData { export type InternalGetValidatorDashboardResponse = ApiDataResponse; export interface VDBPostArchivingReturnData { id: number /* uint64 */; - archived: boolean; + is_archived: boolean; } export interface VDBSummaryStatus { next_sync_count: number /* uint64 */; From fe4860dc3673c60fb9098340f4a5c5f78a33b5b9 Mon Sep 17 00:00:00 2001 From: remoterami Date: Mon, 29 Jul 2024 17:15:24 +0200 Subject: [PATCH 08/15] moved archival handling --- backend/pkg/api/data_access/dummy.go | 2 +- backend/pkg/api/data_access/user.go | 4 ++-- backend/pkg/api/handlers/auth.go | 14 +------------- backend/pkg/api/handlers/common.go | 18 ++++++++++++++++-- backend/pkg/api/handlers/internal.go | 2 +- backend/pkg/api/router.go | 14 +++----------- 6 files changed, 24 insertions(+), 30 deletions(-) diff --git a/backend/pkg/api/data_access/dummy.go b/backend/pkg/api/data_access/dummy.go index 167b3f89d..4ba6cab6e 100644 --- a/backend/pkg/api/data_access/dummy.go +++ b/backend/pkg/api/data_access/dummy.go @@ -483,7 +483,7 @@ func (d *DummyService) GetSearchValidatorsByGraffiti(ctx context.Context, chainI return &r, err } -func (d *DummyService) GetUserValidatorDashboard(ctx context.Context, dashboardId t.VDBIdPrimary) (*t.ValidatorDashboard, error) { +func (d *DummyService) GetUserValidatorDashboard(ctx context.Context, dashboardId t.VDBId) (*t.ValidatorDashboard, error) { r := t.ValidatorDashboard{} // return semi-valid data to not break staging //nolint:errcheck diff --git a/backend/pkg/api/data_access/user.go b/backend/pkg/api/data_access/user.go index 9600c6915..164df33cb 100644 --- a/backend/pkg/api/data_access/user.go +++ b/backend/pkg/api/data_access/user.go @@ -27,7 +27,7 @@ type UserRepository interface { GetUserIdByConfirmationHash(hash string) (uint64, error) GetUserInfo(ctx context.Context, id uint64) (*t.UserInfo, error) GetUserDashboards(ctx context.Context, userId uint64) (*t.UserDashboardsData, error) - GetUserValidatorDashboard(ctx context.Context, dashboardId t.VDBIdPrimary) (*t.ValidatorDashboard, error) + GetUserValidatorDashboard(ctx context.Context, dashboardId t.VDBId) (*t.ValidatorDashboard, error) GetUserValidatorDashboardCount(ctx context.Context, userId uint64, active bool) (uint64, error) } @@ -605,7 +605,7 @@ func (d *DataAccessService) GetUserDashboards(ctx context.Context, userId uint64 return result, nil } -func (d *DataAccessService) GetUserValidatorDashboard(ctx context.Context, dashboardId t.VDBIdPrimary) (*t.ValidatorDashboard, error) { +func (d *DataAccessService) GetUserValidatorDashboard(ctx context.Context, dashboardId t.VDBId) (*t.ValidatorDashboard, error) { // TODO @DATA-ACCESS return d.dummy.GetUserValidatorDashboard(ctx, dashboardId) } diff --git a/backend/pkg/api/handlers/auth.go b/backend/pkg/api/handlers/auth.go index 8558ed576..618ef557c 100644 --- a/backend/pkg/api/handlers/auth.go +++ b/backend/pkg/api/handlers/auth.go @@ -442,7 +442,7 @@ func (h *HandlerService) InternalPutUserPassword(w http.ResponseWriter, r *http. // returns a middleware that checks if user has access to dashboard when a primary id is used // expects a userIdFunc to return user id, probably GetUserIdBySession or GetUserIdByApiKey -func (h *HandlerService) GetVDBAuthMiddleware(userIdFunc func(r *http.Request) (uint64, error), rejectArchived bool) func(http.Handler) http.Handler { +func (h *HandlerService) GetVDBAuthMiddleware(userIdFunc func(r *http.Request) (uint64, error)) func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var err error @@ -476,18 +476,6 @@ func (h *HandlerService) GetVDBAuthMiddleware(userIdFunc func(r *http.Request) ( handleErr(w, newNotFoundErr("dashboard with id %v not found", dashboardId)) return } - if rejectArchived { - db, err := h.dai.GetUserValidatorDashboard(r.Context(), types.VDBIdPrimary(dashboardId)) - if err != nil { - handleErr(w, err) - return - } - if db.IsArchived { - // user does not have access to dashboard - handleErr(w, newConflictErr("dashboard with id %v is archived", dashboardId)) - return - } - } next.ServeHTTP(w, r) }) diff --git a/backend/pkg/api/handlers/common.go b/backend/pkg/api/handlers/common.go index d55c27fdb..5928c39c0 100644 --- a/backend/pkg/api/handlers/common.go +++ b/backend/pkg/api/handlers/common.go @@ -299,8 +299,8 @@ func (h *HandlerService) getDashboardId(ctx context.Context, dashboardIdParam in // handleDashboardId is a helper function to both validate the dashboard id param and convert it to a VDBId. // it should be used as the last validation step for all internal dashboard GET-handlers. -// Modifying handlers (POST, PUT, DELETE) should only accept primary dashboard ids. -func (h *HandlerService) handleDashboardId(ctx context.Context, param string) (*types.VDBId, error) { +// Modifying handlers (POST, PUT, DELETE) should only accept primary dashboard ids and just use checkPrimaryDashboardId. +func (h *HandlerService) handleDashboardIdArchived(ctx context.Context, param string, rejectArchived bool) (*types.VDBId, error) { // validate dashboard id param dashboardIdParam, err := parseDashboardId(param) if err != nil { @@ -311,9 +311,23 @@ func (h *HandlerService) handleDashboardId(ctx context.Context, param string) (* if err != nil { return nil, err } + + if rejectArchived { + dashboardInfo, err := h.dai.GetUserValidatorDashboard(ctx, *dashboardId) + if err != nil { + return nil, err + } + if dashboardInfo.IsArchived { + return nil, newBadRequestErr("can't access archived dashboard") + } + } return dashboardId, nil } +func (h *HandlerService) handleDashboardId(ctx context.Context, param string) (*types.VDBId, error) { + return h.handleDashboardIdArchived(ctx, param, true) +} + func (v *validationError) checkPrimaryDashboardId(param string) types.VDBIdPrimary { return types.VDBIdPrimary(v.checkUint(param, "dashboard_id")) } diff --git a/backend/pkg/api/handlers/internal.go b/backend/pkg/api/handlers/internal.go index 1a75bf901..d6ce373e2 100644 --- a/backend/pkg/api/handlers/internal.go +++ b/backend/pkg/api/handlers/internal.go @@ -308,7 +308,7 @@ func (h *HandlerService) InternalPutValidatorDashboardArchiving(w http.ResponseW } // check conditions for changing archival status - dashboardInfo, err := h.dai.GetUserValidatorDashboard(r.Context(), dashboardId) + dashboardInfo, err := h.dai.GetUserValidatorDashboard(r.Context(), types.VDBId{Id: dashboardId}) if err != nil { handleErr(w, err) return diff --git a/backend/pkg/api/router.go b/backend/pkg/api/router.go index b23e70d99..9c27e6e49 100644 --- a/backend/pkg/api/router.go +++ b/backend/pkg/api/router.go @@ -222,24 +222,16 @@ func addValidatorDashboardRoutes(hs *handlers.HandlerService, publicRouter, inte publicDashboardRouter := publicRouter.PathPrefix(vdbPath).Subrouter() internalDashboardRouter := internalRouter.PathPrefix(vdbPath).Subrouter() - - // allow access to handle dashboard archiving - if !cfg.Frontend.Debug { - publicDashboardRouter.Use(hs.GetVDBAuthMiddleware(hs.GetUserIdByApiKey, false), hs.VDBPublicApiCheckMiddleware) - internalDashboardRouter.Use(hs.GetVDBAuthMiddleware(hs.GetUserIdBySession, false), GetAuthMiddleware(cfg.ApiKeySecret)) - } - publicDashboardRouter.HandleFunc("/{dashboard_id}/archiving", hs.PublicPutValidatorDashboardArchiving).Methods(http.MethodPut, http.MethodOptions) - internalDashboardRouter.HandleFunc("/{dashboard_id}/archiving", hs.InternalPutValidatorDashboardArchiving).Methods(http.MethodPut, http.MethodOptions) - // add middleware to check if user has access to dashboard if !cfg.Frontend.Debug { - publicDashboardRouter.Use(hs.GetVDBAuthMiddleware(hs.GetUserIdByApiKey, true), hs.VDBPublicApiCheckMiddleware) - internalDashboardRouter.Use(hs.GetVDBAuthMiddleware(hs.GetUserIdBySession, true), GetAuthMiddleware(cfg.ApiKeySecret)) + publicDashboardRouter.Use(hs.GetVDBAuthMiddleware(hs.GetUserIdByApiKey), hs.VDBPublicApiCheckMiddleware) + internalDashboardRouter.Use(hs.GetVDBAuthMiddleware(hs.GetUserIdBySession), GetAuthMiddleware(cfg.ApiKeySecret)) } endpoints := []endpoint{ {http.MethodGet, "/{dashboard_id}", hs.PublicGetValidatorDashboard, hs.InternalGetValidatorDashboard}, {http.MethodDelete, "/{dashboard_id}", hs.PublicDeleteValidatorDashboard, hs.InternalDeleteValidatorDashboard}, + {http.MethodPut, "/{dashboard_id}/archiving", hs.PublicPutValidatorDashboardArchiving, hs.InternalPutValidatorDashboardArchiving}, {http.MethodPut, "/{dashboard_id}/name", nil, hs.InternalPutValidatorDashboardName}, {http.MethodPost, "/{dashboard_id}/groups", hs.PublicPostValidatorDashboardGroups, hs.InternalPostValidatorDashboardGroups}, {http.MethodPut, "/{dashboard_id}/groups/{group_id}", hs.PublicPutValidatorDashboardGroups, hs.InternalPutValidatorDashboardGroups}, From cbb2ea593ae2ec021d36b1c2b5602007de3f6259 Mon Sep 17 00:00:00 2001 From: remoterami Date: Mon, 29 Jul 2024 17:25:41 +0200 Subject: [PATCH 09/15] simplified --- backend/pkg/api/handlers/common.go | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/backend/pkg/api/handlers/common.go b/backend/pkg/api/handlers/common.go index 5928c39c0..58d8689e5 100644 --- a/backend/pkg/api/handlers/common.go +++ b/backend/pkg/api/handlers/common.go @@ -300,7 +300,7 @@ func (h *HandlerService) getDashboardId(ctx context.Context, dashboardIdParam in // handleDashboardId is a helper function to both validate the dashboard id param and convert it to a VDBId. // it should be used as the last validation step for all internal dashboard GET-handlers. // Modifying handlers (POST, PUT, DELETE) should only accept primary dashboard ids and just use checkPrimaryDashboardId. -func (h *HandlerService) handleDashboardIdArchived(ctx context.Context, param string, rejectArchived bool) (*types.VDBId, error) { +func (h *HandlerService) handleDashboardId(ctx context.Context, param string) (*types.VDBId, error) { // validate dashboard id param dashboardIdParam, err := parseDashboardId(param) if err != nil { @@ -312,22 +312,16 @@ func (h *HandlerService) handleDashboardIdArchived(ctx context.Context, param st return nil, err } - if rejectArchived { - dashboardInfo, err := h.dai.GetUserValidatorDashboard(ctx, *dashboardId) - if err != nil { - return nil, err - } - if dashboardInfo.IsArchived { - return nil, newBadRequestErr("can't access archived dashboard") - } + dashboardInfo, err := h.dai.GetUserValidatorDashboard(ctx, *dashboardId) + if err != nil { + return nil, err + } + if dashboardInfo.IsArchived { + return nil, newBadRequestErr("can't access archived dashboard") } return dashboardId, nil } -func (h *HandlerService) handleDashboardId(ctx context.Context, param string) (*types.VDBId, error) { - return h.handleDashboardIdArchived(ctx, param, true) -} - func (v *validationError) checkPrimaryDashboardId(param string) types.VDBIdPrimary { return types.VDBIdPrimary(v.checkUint(param, "dashboard_id")) } From 44630abb1eb099a72914d8d146663426510d3043 Mon Sep 17 00:00:00 2001 From: remoterami Date: Tue, 30 Jul 2024 10:46:17 +0200 Subject: [PATCH 10/15] moved function --- backend/pkg/api/data_access/dummy.go | 18 +++++++++--------- backend/pkg/api/data_access/user.go | 6 ------ backend/pkg/api/data_access/vdb_helpers.go | 1 + backend/pkg/api/data_access/vdb_management.go | 5 +++++ backend/pkg/api/handlers/common.go | 2 +- backend/pkg/api/handlers/internal.go | 2 +- backend/pkg/api/types/dashboard.go | 2 +- frontend/types/api/dashboard.ts | 2 +- 8 files changed, 19 insertions(+), 19 deletions(-) diff --git a/backend/pkg/api/data_access/dummy.go b/backend/pkg/api/data_access/dummy.go index 4ba6cab6e..e6d40cfe9 100644 --- a/backend/pkg/api/data_access/dummy.go +++ b/backend/pkg/api/data_access/dummy.go @@ -155,6 +155,15 @@ func (d *DummyService) GetValidatorDashboardInfoByPublicId(ctx context.Context, return &r, err } +func (d *DummyService) GetValidatorDashboard(ctx context.Context, dashboardId t.VDBId) (*t.ValidatorDashboard, error) { + r := t.ValidatorDashboard{} + // return semi-valid data to not break staging + //nolint:errcheck + commonFakeData(&r) + r.IsArchived = false + return &r, nil +} + func (d *DummyService) GetValidatorDashboardName(ctx context.Context, dashboardId t.VDBIdPrimary) (string, error) { r := "" err := commonFakeData(&r) @@ -483,15 +492,6 @@ func (d *DummyService) GetSearchValidatorsByGraffiti(ctx context.Context, chainI return &r, err } -func (d *DummyService) GetUserValidatorDashboard(ctx context.Context, dashboardId t.VDBId) (*t.ValidatorDashboard, error) { - r := t.ValidatorDashboard{} - // return semi-valid data to not break staging - //nolint:errcheck - commonFakeData(&r) - r.IsArchived = false - return &r, nil -} - func (d *DummyService) GetUserValidatorDashboardCount(ctx context.Context, userId uint64, active bool) (uint64, error) { r := uint64(0) err := commonFakeData(&r) diff --git a/backend/pkg/api/data_access/user.go b/backend/pkg/api/data_access/user.go index 164df33cb..48b3bdc5b 100644 --- a/backend/pkg/api/data_access/user.go +++ b/backend/pkg/api/data_access/user.go @@ -27,7 +27,6 @@ type UserRepository interface { GetUserIdByConfirmationHash(hash string) (uint64, error) GetUserInfo(ctx context.Context, id uint64) (*t.UserInfo, error) GetUserDashboards(ctx context.Context, userId uint64) (*t.UserDashboardsData, error) - GetUserValidatorDashboard(ctx context.Context, dashboardId t.VDBId) (*t.ValidatorDashboard, error) GetUserValidatorDashboardCount(ctx context.Context, userId uint64, active bool) (uint64, error) } @@ -605,11 +604,6 @@ func (d *DataAccessService) GetUserDashboards(ctx context.Context, userId uint64 return result, nil } -func (d *DataAccessService) GetUserValidatorDashboard(ctx context.Context, dashboardId t.VDBId) (*t.ValidatorDashboard, error) { - // TODO @DATA-ACCESS - return d.dummy.GetUserValidatorDashboard(ctx, dashboardId) -} - // return number of active / archived dashboards func (d *DataAccessService) GetUserValidatorDashboardCount(ctx context.Context, userId uint64, active bool) (uint64, error) { // @DATA-ACCESS return number of dashboards depending on archival status (see comment above) diff --git a/backend/pkg/api/data_access/vdb_helpers.go b/backend/pkg/api/data_access/vdb_helpers.go index e82de967b..f63f1ac84 100644 --- a/backend/pkg/api/data_access/vdb_helpers.go +++ b/backend/pkg/api/data_access/vdb_helpers.go @@ -19,6 +19,7 @@ import ( type ValidatorDashboardRepository interface { GetValidatorDashboardInfo(ctx context.Context, dashboardId t.VDBIdPrimary) (*t.DashboardInfo, error) GetValidatorDashboardInfoByPublicId(ctx context.Context, publicDashboardId t.VDBIdPublic) (*t.DashboardInfo, error) + GetValidatorDashboard(ctx context.Context, dashboardId t.VDBId) (*t.ValidatorDashboard, error) GetValidatorDashboardName(ctx context.Context, dashboardId t.VDBIdPrimary) (string, error) CreateValidatorDashboard(ctx context.Context, userId uint64, name string, network uint64) (*t.VDBPostReturnData, error) RemoveValidatorDashboard(ctx context.Context, dashboardId t.VDBIdPrimary) error diff --git a/backend/pkg/api/data_access/vdb_management.go b/backend/pkg/api/data_access/vdb_management.go index 76184a1cc..54967fc17 100644 --- a/backend/pkg/api/data_access/vdb_management.go +++ b/backend/pkg/api/data_access/vdb_management.go @@ -57,6 +57,11 @@ func (d *DataAccessService) GetValidatorDashboardInfoByPublicId(ctx context.Cont return result, err } +func (d *DataAccessService) GetValidatorDashboard(ctx context.Context, dashboardId t.VDBId) (*t.ValidatorDashboard, error) { + // TODO @DATA-ACCESS + return d.dummy.GetValidatorDashboard(ctx, dashboardId) +} + func (d *DataAccessService) GetValidatorDashboardName(ctx context.Context, dashboardId t.VDBIdPrimary) (string, error) { var name string err := d.alloyReader.Get(&name, ` diff --git a/backend/pkg/api/handlers/common.go b/backend/pkg/api/handlers/common.go index 58d8689e5..e26963909 100644 --- a/backend/pkg/api/handlers/common.go +++ b/backend/pkg/api/handlers/common.go @@ -312,7 +312,7 @@ func (h *HandlerService) handleDashboardId(ctx context.Context, param string) (* return nil, err } - dashboardInfo, err := h.dai.GetUserValidatorDashboard(ctx, *dashboardId) + dashboardInfo, err := h.dai.GetValidatorDashboard(ctx, *dashboardId) if err != nil { return nil, err } diff --git a/backend/pkg/api/handlers/internal.go b/backend/pkg/api/handlers/internal.go index d6ce373e2..b0e630be5 100644 --- a/backend/pkg/api/handlers/internal.go +++ b/backend/pkg/api/handlers/internal.go @@ -308,7 +308,7 @@ func (h *HandlerService) InternalPutValidatorDashboardArchiving(w http.ResponseW } // check conditions for changing archival status - dashboardInfo, err := h.dai.GetUserValidatorDashboard(r.Context(), types.VDBId{Id: dashboardId}) + dashboardInfo, err := h.dai.GetValidatorDashboard(r.Context(), types.VDBId{Id: dashboardId}) if err != nil { handleErr(w, err) return diff --git a/backend/pkg/api/types/dashboard.go b/backend/pkg/api/types/dashboard.go index ed903ac48..fdf5947be 100644 --- a/backend/pkg/api/types/dashboard.go +++ b/backend/pkg/api/types/dashboard.go @@ -9,7 +9,7 @@ type ValidatorDashboard struct { Name string `json:"name"` PublicIds []VDBPublicId `json:"public_ids,omitempty"` IsArchived bool `json:"is_archived"` - ArchivedReason string `json:"archived_reason,omitempty"` // dashboard_limit, validator_limit, group_limit, none + ArchivedReason string `json:"archived_reason,omitempty" tstype:"'dashboard_limit' | 'validator_limit' | 'group_limit'"` ValidatorCount uint64 `json:"validator_count"` GroupCount uint64 `json:"group_count"` } diff --git a/frontend/types/api/dashboard.ts b/frontend/types/api/dashboard.ts index 1b9900d3a..37fa19546 100644 --- a/frontend/types/api/dashboard.ts +++ b/frontend/types/api/dashboard.ts @@ -14,7 +14,7 @@ export interface ValidatorDashboard { name: string; public_ids?: VDBPublicId[]; is_archived: boolean; - archived_reason?: string; // dashboard_limit, validator_limit, group_limit, none + archived_reason?: 'dashboard_limit' | 'validator_limit' | 'group_limit'; validator_count: number /* uint64 */; group_count: number /* uint64 */; } From b0ac2c0b927eec72356f4e1d6e33726e10113b93 Mon Sep 17 00:00:00 2001 From: remoterami Date: Tue, 30 Jul 2024 10:59:13 +0200 Subject: [PATCH 11/15] removed archival auth checks --- backend/pkg/api/handlers/common.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/backend/pkg/api/handlers/common.go b/backend/pkg/api/handlers/common.go index e26963909..3ae3b3157 100644 --- a/backend/pkg/api/handlers/common.go +++ b/backend/pkg/api/handlers/common.go @@ -312,13 +312,6 @@ func (h *HandlerService) handleDashboardId(ctx context.Context, param string) (* return nil, err } - dashboardInfo, err := h.dai.GetValidatorDashboard(ctx, *dashboardId) - if err != nil { - return nil, err - } - if dashboardInfo.IsArchived { - return nil, newBadRequestErr("can't access archived dashboard") - } return dashboardId, nil } From 024cd8aefc25ff131fe0dddcb3b04e3e9e05c31c Mon Sep 17 00:00:00 2001 From: remoterami Date: Tue, 30 Jul 2024 11:36:32 +0200 Subject: [PATCH 12/15] removed upper block number limit --- backend/pkg/api/handlers/common.go | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/backend/pkg/api/handlers/common.go b/backend/pkg/api/handlers/common.go index 39f2340e8..342d92fac 100644 --- a/backend/pkg/api/handlers/common.go +++ b/backend/pkg/api/handlers/common.go @@ -16,6 +16,7 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/gobitfly/beaconchain/pkg/commons/log" + "github.com/gorilla/mux" "github.com/invopop/jsonschema" "github.com/xeipuuv/gojsonschema" @@ -362,20 +363,18 @@ func (h *HandlerService) getDashboardPremiumPerks(ctx context.Context, id types. // helper function to unify handling of block detail request validation func (h *HandlerService) validateBlockRequest(r *http.Request) (uint64, uint64, error) { var v validationError - req := struct { - Network intOrString `json:"network"` - Block string `json:"block"` - }{} - if err := v.checkBody(&req, r); err != nil { - return 0, 0, err - } - chainId := v.checkNetwork(req.Network) - block, err := h.dai.GetLatestBlock() - if err != nil { - return 0, 0, err - } - if req.Block != "latest" { - block = v.checkUintMinMax(req.Block, 0, block, "block") + var err error + chainId := v.checkNetworkParameter(mux.Vars(r)["network"]) + var block uint64 + switch blockParam := mux.Vars(r)["block"]; blockParam { + // possibly add other values like "genesis", "finalized", hardforks etc. later + case "latest": + block, err = h.dai.GetLatestBlock() + if err != nil { + return 0, 0, err + } + default: + block = v.checkUint(blockParam, "block") } if v.hasErrors() { return 0, 0, v From ff9e4778da2fcb26ca09d517466ac7cda20d406b Mon Sep 17 00:00:00 2001 From: remoterami Date: Wed, 31 Jul 2024 12:23:03 +0200 Subject: [PATCH 13/15] added slot endpoints --- backend/pkg/api/data_access/block.go | 82 +++++++++ backend/pkg/api/data_access/data_access.go | 1 + backend/pkg/api/data_access/dummy.go | 60 +++++++ backend/pkg/api/data_access/header.go | 5 + backend/pkg/api/handlers/common.go | 17 +- backend/pkg/api/handlers/internal.go | 191 ++++++++++++++++++++- backend/pkg/api/handlers/public.go | 4 + backend/pkg/api/router.go | 14 +- 8 files changed, 352 insertions(+), 22 deletions(-) diff --git a/backend/pkg/api/data_access/block.go b/backend/pkg/api/data_access/block.go index 9a5c17f32..65e63b408 100644 --- a/backend/pkg/api/data_access/block.go +++ b/backend/pkg/api/data_access/block.go @@ -16,6 +16,16 @@ type BlockRepository interface { GetBlockBlsChanges(ctx context.Context, chainId, block uint64) ([]t.BlockBlsChangeTableRow, error) GetBlockVoluntaryExits(ctx context.Context, chainId, block uint64) ([]t.BlockVoluntaryExitTableRow, error) GetBlockBlobs(ctx context.Context, chainId, block uint64) ([]t.BlockBlobTableRow, error) + + GetSlot(ctx context.Context, chainId, block uint64) (*t.BlockSummary, error) + GetSlotOverview(ctx context.Context, chainId, block uint64) (*t.BlockOverview, error) + GetSlotTransactions(ctx context.Context, chainId, block uint64) ([]t.BlockTransactionTableRow, error) + GetSlotVotes(ctx context.Context, chainId, block uint64) ([]t.BlockVoteTableRow, error) + GetSlotAttestations(ctx context.Context, chainId, block uint64) ([]t.BlockAttestationTableRow, error) + GetSlotWithdrawals(ctx context.Context, chainId, block uint64) ([]t.BlockWithdrawalTableRow, error) + GetSlotBlsChanges(ctx context.Context, chainId, block uint64) ([]t.BlockBlsChangeTableRow, error) + GetSlotVoluntaryExits(ctx context.Context, chainId, block uint64) ([]t.BlockVoluntaryExitTableRow, error) + GetSlotBlobs(ctx context.Context, chainId, block uint64) ([]t.BlockBlobTableRow, error) } func (d *DataAccessService) GetBlock(ctx context.Context, chainId, block uint64) (*t.BlockSummary, error) { @@ -62,3 +72,75 @@ func (d *DataAccessService) GetBlockBlobs(ctx context.Context, chainId, block ui // @DATA-ACCESS return d.dummy.GetBlockBlobs(ctx, chainId, block) } + +func (d *DataAccessService) GetSlot(ctx context.Context, chainId, slot uint64) (*t.BlockSummary, error) { + block, err := d.GetBlockHeightAt(slot) + if err != nil { + return nil, err + } + return d.GetBlock(ctx, chainId, block) +} + +func (d *DataAccessService) GetSlotOverview(ctx context.Context, chainId, slot uint64) (*t.BlockOverview, error) { + block, err := d.GetBlockHeightAt(slot) + if err != nil { + return nil, err + } + return d.GetBlockOverview(ctx, chainId, block) +} + +func (d *DataAccessService) GetSlotTransactions(ctx context.Context, chainId, slot uint64) ([]t.BlockTransactionTableRow, error) { + block, err := d.GetBlockHeightAt(slot) + if err != nil { + return nil, err + } + return d.GetBlockTransactions(ctx, chainId, block) +} + +func (d *DataAccessService) GetSlotVotes(ctx context.Context, chainId, slot uint64) ([]t.BlockVoteTableRow, error) { + block, err := d.GetBlockHeightAt(slot) + if err != nil { + return nil, err + } + return d.GetBlockVotes(ctx, chainId, block) +} + +func (d *DataAccessService) GetSlotAttestations(ctx context.Context, chainId, slot uint64) ([]t.BlockAttestationTableRow, error) { + block, err := d.GetBlockHeightAt(slot) + if err != nil { + return nil, err + } + return d.GetBlockAttestations(ctx, chainId, block) +} + +func (d *DataAccessService) GetSlotWithdrawals(ctx context.Context, chainId, slot uint64) ([]t.BlockWithdrawalTableRow, error) { + block, err := d.GetBlockHeightAt(slot) + if err != nil { + return nil, err + } + return d.GetBlockWithdrawals(ctx, chainId, block) +} + +func (d *DataAccessService) GetSlotBlsChanges(ctx context.Context, chainId, slot uint64) ([]t.BlockBlsChangeTableRow, error) { + block, err := d.GetBlockHeightAt(slot) + if err != nil { + return nil, err + } + return d.GetBlockBlsChanges(ctx, chainId, block) +} + +func (d *DataAccessService) GetSlotVoluntaryExits(ctx context.Context, chainId, slot uint64) ([]t.BlockVoluntaryExitTableRow, error) { + block, err := d.GetBlockHeightAt(slot) + if err != nil { + return nil, err + } + return d.GetBlockVoluntaryExits(ctx, chainId, block) +} + +func (d *DataAccessService) GetSlotBlobs(ctx context.Context, chainId, slot uint64) ([]t.BlockBlobTableRow, error) { + block, err := d.GetBlockHeightAt(slot) + if err != nil { + return nil, err + } + return d.GetBlockBlobs(ctx, chainId, block) +} diff --git a/backend/pkg/api/data_access/data_access.go b/backend/pkg/api/data_access/data_access.go index de9a2c4a2..5dbb915c3 100644 --- a/backend/pkg/api/data_access/data_access.go +++ b/backend/pkg/api/data_access/data_access.go @@ -31,6 +31,7 @@ type DataAccessor interface { GetLatestSlot() (uint64, error) GetLatestBlock() (uint64, error) + GetBlockHeightAt(slot uint64) (uint64, error) GetLatestExchangeRates() ([]t.EthConversionRate, error) GetProductSummary(ctx context.Context) (*t.ProductSummary, error) diff --git a/backend/pkg/api/data_access/dummy.go b/backend/pkg/api/data_access/dummy.go index efa72b535..52d615433 100644 --- a/backend/pkg/api/data_access/dummy.go +++ b/backend/pkg/api/data_access/dummy.go @@ -69,6 +69,12 @@ func (d *DummyService) GetLatestBlock() (uint64, error) { return r, err } +func (d *DummyService) GetBlockHeightAt(slot uint64) (uint64, error) { + r := uint64(0) + err := commonFakeData(&r) + return r, err +} + func (d *DummyService) GetLatestExchangeRates() ([]t.EthConversionRate, error) { r := []t.EthConversionRate{} err := commonFakeData(&r) @@ -678,3 +684,57 @@ func (d *DummyService) GetBlockBlobs(ctx context.Context, chainId, block uint64) err := commonFakeData(&r) return r, err } + +func (d *DummyService) GetSlot(ctx context.Context, chainId, block uint64) (*t.BlockSummary, error) { + r := t.BlockSummary{} + err := commonFakeData(&r) + return &r, err +} + +func (d *DummyService) GetSlotOverview(ctx context.Context, chainId, block uint64) (*t.BlockOverview, error) { + r := t.BlockOverview{} + err := commonFakeData(&r) + return &r, err +} + +func (d *DummyService) GetSlotTransactions(ctx context.Context, chainId, block uint64) ([]t.BlockTransactionTableRow, error) { + r := []t.BlockTransactionTableRow{} + err := commonFakeData(&r) + return r, err +} + +func (d *DummyService) GetSlotVotes(ctx context.Context, chainId, block uint64) ([]t.BlockVoteTableRow, error) { + r := []t.BlockVoteTableRow{} + err := commonFakeData(&r) + return r, err +} + +func (d *DummyService) GetSlotAttestations(ctx context.Context, chainId, block uint64) ([]t.BlockAttestationTableRow, error) { + r := []t.BlockAttestationTableRow{} + err := commonFakeData(&r) + return r, err +} + +func (d *DummyService) GetSlotWithdrawals(ctx context.Context, chainId, block uint64) ([]t.BlockWithdrawalTableRow, error) { + r := []t.BlockWithdrawalTableRow{} + err := commonFakeData(&r) + return r, err +} + +func (d *DummyService) GetSlotBlsChanges(ctx context.Context, chainId, block uint64) ([]t.BlockBlsChangeTableRow, error) { + r := []t.BlockBlsChangeTableRow{} + err := commonFakeData(&r) + return r, err +} + +func (d *DummyService) GetSlotVoluntaryExits(ctx context.Context, chainId, block uint64) ([]t.BlockVoluntaryExitTableRow, error) { + r := []t.BlockVoluntaryExitTableRow{} + err := commonFakeData(&r) + return r, err +} + +func (d *DummyService) GetSlotBlobs(ctx context.Context, chainId, block uint64) ([]t.BlockBlobTableRow, error) { + r := []t.BlockBlobTableRow{} + err := commonFakeData(&r) + return r, err +} diff --git a/backend/pkg/api/data_access/header.go b/backend/pkg/api/data_access/header.go index 54627825d..9363483bb 100644 --- a/backend/pkg/api/data_access/header.go +++ b/backend/pkg/api/data_access/header.go @@ -16,6 +16,11 @@ func (d *DataAccessService) GetLatestBlock() (uint64, error) { return d.dummy.GetLatestBlock() } +func (d *DataAccessService) GetBlockHeightAt(slot uint64) (uint64, error) { + // @DATA-ACCESS implement; return error if no block at slot + return d.dummy.GetBlockHeightAt(slot) +} + func (d *DataAccessService) GetLatestExchangeRates() ([]t.EthConversionRate, error) { result := []t.EthConversionRate{} diff --git a/backend/pkg/api/handlers/common.go b/backend/pkg/api/handlers/common.go index 342d92fac..52d42a147 100644 --- a/backend/pkg/api/handlers/common.go +++ b/backend/pkg/api/handlers/common.go @@ -361,26 +361,29 @@ func (h *HandlerService) getDashboardPremiumPerks(ctx context.Context, id types. } // helper function to unify handling of block detail request validation -func (h *HandlerService) validateBlockRequest(r *http.Request) (uint64, uint64, error) { +func (h *HandlerService) validateBlockRequest(r *http.Request, paramName string) (uint64, uint64, error) { var v validationError var err error chainId := v.checkNetworkParameter(mux.Vars(r)["network"]) - var block uint64 - switch blockParam := mux.Vars(r)["block"]; blockParam { + var value uint64 + switch paramValue := mux.Vars(r)[paramName]; paramValue { // possibly add other values like "genesis", "finalized", hardforks etc. later case "latest": - block, err = h.dai.GetLatestBlock() + if paramName == "block" { + value, err = h.dai.GetLatestBlock() + } else if paramName == "slot" { + value, err = h.dai.GetLatestSlot() + } if err != nil { return 0, 0, err } default: - block = v.checkUint(blockParam, "block") + value = v.checkUint(paramValue, paramName) } if v.hasErrors() { return 0, 0, v } - - return chainId, block, nil + return chainId, value, nil } // checkGroupId validates the given group id and returns it as an int64. diff --git a/backend/pkg/api/handlers/internal.go b/backend/pkg/api/handlers/internal.go index ca883d670..889cf62af 100644 --- a/backend/pkg/api/handlers/internal.go +++ b/backend/pkg/api/handlers/internal.go @@ -1903,7 +1903,7 @@ func (h *HandlerService) InternalPostUserNotificationsTestWebhook(w http.Respons // Blocks func (h *HandlerService) InternalGetBlock(w http.ResponseWriter, r *http.Request) { - chainId, block, err := h.validateBlockRequest(r) + chainId, block, err := h.validateBlockRequest(r, "block") if err != nil { handleErr(w, err) return @@ -1922,7 +1922,7 @@ func (h *HandlerService) InternalGetBlock(w http.ResponseWriter, r *http.Request } func (h *HandlerService) InternalGetBlockOverview(w http.ResponseWriter, r *http.Request) { - chainId, block, err := h.validateBlockRequest(r) + chainId, block, err := h.validateBlockRequest(r, "block") if err != nil { handleErr(w, err) return @@ -1940,7 +1940,7 @@ func (h *HandlerService) InternalGetBlockOverview(w http.ResponseWriter, r *http } func (h *HandlerService) InternalGetBlockTransactions(w http.ResponseWriter, r *http.Request) { - chainId, block, err := h.validateBlockRequest(r) + chainId, block, err := h.validateBlockRequest(r, "block") if err != nil { handleErr(w, err) return @@ -1959,7 +1959,7 @@ func (h *HandlerService) InternalGetBlockTransactions(w http.ResponseWriter, r * } func (h *HandlerService) InternalGetBlockVotes(w http.ResponseWriter, r *http.Request) { - chainId, block, err := h.validateBlockRequest(r) + chainId, block, err := h.validateBlockRequest(r, "block") if err != nil { handleErr(w, err) return @@ -1978,7 +1978,7 @@ func (h *HandlerService) InternalGetBlockVotes(w http.ResponseWriter, r *http.Re } func (h *HandlerService) InternalGetBlockAttestations(w http.ResponseWriter, r *http.Request) { - chainId, block, err := h.validateBlockRequest(r) + chainId, block, err := h.validateBlockRequest(r, "block") if err != nil { handleErr(w, err) return @@ -1997,7 +1997,7 @@ func (h *HandlerService) InternalGetBlockAttestations(w http.ResponseWriter, r * } func (h *HandlerService) InternalGetBlockWithdrawals(w http.ResponseWriter, r *http.Request) { - chainId, block, err := h.validateBlockRequest(r) + chainId, block, err := h.validateBlockRequest(r, "block") if err != nil { handleErr(w, err) return @@ -2016,7 +2016,7 @@ func (h *HandlerService) InternalGetBlockWithdrawals(w http.ResponseWriter, r *h } func (h *HandlerService) InternalGetBlockBlsChanges(w http.ResponseWriter, r *http.Request) { - chainId, block, err := h.validateBlockRequest(r) + chainId, block, err := h.validateBlockRequest(r, "block") if err != nil { handleErr(w, err) return @@ -2035,7 +2035,7 @@ func (h *HandlerService) InternalGetBlockBlsChanges(w http.ResponseWriter, r *ht } func (h *HandlerService) InternalGetBlockVoluntaryExits(w http.ResponseWriter, r *http.Request) { - chainId, block, err := h.validateBlockRequest(r) + chainId, block, err := h.validateBlockRequest(r, "block") if err != nil { handleErr(w, err) return @@ -2054,7 +2054,7 @@ func (h *HandlerService) InternalGetBlockVoluntaryExits(w http.ResponseWriter, r } func (h *HandlerService) InternalGetBlockBlobs(w http.ResponseWriter, r *http.Request) { - chainId, block, err := h.validateBlockRequest(r) + chainId, block, err := h.validateBlockRequest(r, "block") if err != nil { handleErr(w, err) return @@ -2071,3 +2071,176 @@ func (h *HandlerService) InternalGetBlockBlobs(w http.ResponseWriter, r *http.Re } returnOk(w, response) } + +// -------------------------------------- +// Slots + +func (h *HandlerService) InternalGetSlot(w http.ResponseWriter, r *http.Request) { + chainId, block, err := h.validateBlockRequest(r, "slot") + if err != nil { + handleErr(w, err) + return + } + + data, err := h.dai.GetSlot(r.Context(), chainId, block) + if err != nil { + handleErr(w, err) + return + } + + response := types.InternalGetBlockResponse{ + Data: *data, + } + returnOk(w, response) +} + +func (h *HandlerService) InternalGetSlotOverview(w http.ResponseWriter, r *http.Request) { + chainId, block, err := h.validateBlockRequest(r, "slot") + if err != nil { + handleErr(w, err) + return + } + + data, err := h.dai.GetSlotOverview(r.Context(), chainId, block) + if err != nil { + handleErr(w, err) + return + } + response := types.InternalGetBlockOverviewResponse{ + Data: *data, + } + returnOk(w, response) +} + +func (h *HandlerService) InternalGetSlotTransactions(w http.ResponseWriter, r *http.Request) { + chainId, block, err := h.validateBlockRequest(r, "slot") + if err != nil { + handleErr(w, err) + return + } + + data, err := h.dai.GetSlotTransactions(r.Context(), chainId, block) + if err != nil { + handleErr(w, err) + return + } + + response := types.InternalGetBlockTransactionsResponse{ + Data: data, + } + returnOk(w, response) +} + +func (h *HandlerService) InternalGetSlotVotes(w http.ResponseWriter, r *http.Request) { + chainId, block, err := h.validateBlockRequest(r, "slot") + if err != nil { + handleErr(w, err) + return + } + + data, err := h.dai.GetSlotVotes(r.Context(), chainId, block) + if err != nil { + handleErr(w, err) + return + } + + response := types.InternalGetBlockVotesResponse{ + Data: data, + } + returnOk(w, response) +} + +func (h *HandlerService) InternalGetSlotAttestations(w http.ResponseWriter, r *http.Request) { + chainId, block, err := h.validateBlockRequest(r, "slot") + if err != nil { + handleErr(w, err) + return + } + + data, err := h.dai.GetSlotAttestations(r.Context(), chainId, block) + if err != nil { + handleErr(w, err) + return + } + + response := types.InternalGetBlockAttestationsResponse{ + Data: data, + } + returnOk(w, response) +} + +func (h *HandlerService) InternalGetSlotWithdrawals(w http.ResponseWriter, r *http.Request) { + chainId, block, err := h.validateBlockRequest(r, "slot") + if err != nil { + handleErr(w, err) + return + } + + data, err := h.dai.GetSlotWithdrawals(r.Context(), chainId, block) + if err != nil { + handleErr(w, err) + return + } + + response := types.InternalGetBlockWtihdrawalsResponse{ + Data: data, + } + returnOk(w, response) +} + +func (h *HandlerService) InternalGetSlotBlsChanges(w http.ResponseWriter, r *http.Request) { + chainId, block, err := h.validateBlockRequest(r, "slot") + if err != nil { + handleErr(w, err) + return + } + + data, err := h.dai.GetSlotBlsChanges(r.Context(), chainId, block) + if err != nil { + handleErr(w, err) + return + } + + response := types.InternalGetBlockBlsChangesResponse{ + Data: data, + } + returnOk(w, response) +} + +func (h *HandlerService) InternalGetSlotVoluntaryExits(w http.ResponseWriter, r *http.Request) { + chainId, block, err := h.validateBlockRequest(r, "slot") + if err != nil { + handleErr(w, err) + return + } + + data, err := h.dai.GetSlotVoluntaryExits(r.Context(), chainId, block) + if err != nil { + handleErr(w, err) + return + } + + response := types.InternalGetBlockVoluntaryExitsResponse{ + Data: data, + } + returnOk(w, response) +} + +func (h *HandlerService) InternalGetSlotBlobs(w http.ResponseWriter, r *http.Request) { + chainId, block, err := h.validateBlockRequest(r, "slot") + if err != nil { + handleErr(w, err) + return + } + + data, err := h.dai.GetSlotBlobs(r.Context(), chainId, block) + if err != nil { + handleErr(w, err) + return + } + + response := types.InternalGetBlockBlobsResponse{ + Data: data, + } + returnOk(w, response) +} diff --git a/backend/pkg/api/handlers/public.go b/backend/pkg/api/handlers/public.go index 27de72d21..576e2b7da 100644 --- a/backend/pkg/api/handlers/public.go +++ b/backend/pkg/api/handlers/public.go @@ -447,6 +447,10 @@ func (h *HandlerService) PublicGetNetworkSlotAttestations(w http.ResponseWriter, returnOk(w, nil) } +func (h *HandlerService) PublicGetNetworkSlotVotes(w http.ResponseWriter, r *http.Request) { + returnOk(w, nil) +} + func (h *HandlerService) PublicGetNetworkBlockAttestations(w http.ResponseWriter, r *http.Request) { returnOk(w, nil) } diff --git a/backend/pkg/api/router.go b/backend/pkg/api/router.go index c485bb32c..35ed2ac66 100644 --- a/backend/pkg/api/router.go +++ b/backend/pkg/api/router.go @@ -142,7 +142,9 @@ func addRoutes(hs *handlers.HandlerService, publicRouter, internalRouter *mux.Ro {http.MethodGet, "/networks/{network}/blocks/{block}/overview", hs.PublicGetNetworkBlock, hs.InternalGetBlockOverview}, {http.MethodGet, "/networks/{network}/blocks/{block}/votes", hs.PublicGetNetworkBlockVotes, hs.InternalGetBlockVotes}, {http.MethodGet, "/networks/{network}/slots", hs.PublicGetNetworkSlots, nil}, - {http.MethodGet, "/networks/{network}/slots/{slot}", hs.PublicGetNetworkSlot, nil}, + {http.MethodGet, "/networks/{network}/slots/{slot}", nil, hs.InternalGetSlot}, + {http.MethodGet, "/networks/{network}/slots/{slot}/overview", hs.PublicGetNetworkSlot, hs.InternalGetSlotOverview}, + {http.MethodGet, "/networks/{network}/slots/{slot}/votes", hs.PublicGetNetworkSlotVotes, hs.InternalGetSlotVotes}, {http.MethodGet, "/networks/{network}/validators/{validator}/blocks", hs.PublicGetNetworkValidatorBlocks, nil}, {http.MethodGet, "/networks/{network}/addresses/{address}/priority-fee-blocks", hs.PublicGetNetworkAddressPriorityFeeBlocks, nil}, {http.MethodGet, "/networks/{network}/addresses/{address}/proposer-reward-blocks", hs.PublicGetNetworkAddressProposerRewardBlocks, nil}, @@ -153,7 +155,7 @@ func addRoutes(hs *handlers.HandlerService, publicRouter, internalRouter *mux.Ro {http.MethodGet, "/networks/{network}/validators/{validator}/attestations", hs.PublicGetNetworkValidatorAttestations, nil}, {http.MethodGet, "/networks/{network}/epochs/{epoch}/attestations", hs.PublicGetNetworkEpochAttestations, nil}, - {http.MethodGet, "/networks/{network}/slots/{slot}/attestations", hs.PublicGetNetworkSlotAttestations, nil}, + {http.MethodGet, "/networks/{network}/slots/{slot}/attestations", hs.PublicGetNetworkSlotAttestations, hs.InternalGetSlotAttestations}, {http.MethodGet, "/networks/{network}/blocks/{block}/attestations", hs.PublicGetNetworkBlockAttestations, hs.InternalGetBlockAttestations}, {http.MethodGet, "/networks/{network}/aggregated-attestations", hs.PublicGetNetworkAggregatedAttestations, nil}, @@ -170,14 +172,14 @@ func addRoutes(hs *handlers.HandlerService, publicRouter, internalRouter *mux.Ro {http.MethodGet, "/networks/{network}/transactions/{hash}/deposits", hs.PublicGetNetworkTransactionDeposits, nil}, {http.MethodGet, "/networks/{network}/withdrawals", hs.PublicGetNetworkWithdrawals, nil}, - {http.MethodGet, "/networks/{network}/slots/{slot}/withdrawals", hs.PublicGetNetworkSlotWithdrawals, nil}, + {http.MethodGet, "/networks/{network}/slots/{slot}/withdrawals", hs.PublicGetNetworkSlotWithdrawals, hs.InternalGetSlotWithdrawals}, {http.MethodGet, "/networks/{network}/blocks/{block}/withdrawals", hs.PublicGetNetworkBlockWithdrawals, hs.InternalGetBlockWithdrawals}, {http.MethodGet, "/networks/{network}/validators/{validator}/withdrawals", hs.PublicGetNetworkValidatorWithdrawals, nil}, {http.MethodGet, "/networks/{network}/withdrawal-credentials/{credential}/withdrawals", hs.PublicGetNetworkWithdrawalCredentialWithdrawals, nil}, {http.MethodGet, "/networks/{network}/voluntary-exits", hs.PublicGetNetworkVoluntaryExits, nil}, {http.MethodGet, "/networks/{network}/epochs/{epoch}/voluntary-exits", hs.PublicGetNetworkEpochVoluntaryExits, nil}, - {http.MethodGet, "/networks/{network}/slots/{slot}/voluntary-exits", hs.PublicGetNetworkSlotVoluntaryExits, nil}, + {http.MethodGet, "/networks/{network}/slots/{slot}/voluntary-exits", hs.PublicGetNetworkSlotVoluntaryExits, hs.InternalGetSlotVoluntaryExits}, {http.MethodGet, "/networks/{network}/blocks/{block}/voluntary-exits", hs.PublicGetNetworkBlockVoluntaryExits, hs.InternalGetBlockVoluntaryExits}, {http.MethodGet, "/networks/{network}/addresses/{address}/balance-history", hs.PublicGetNetworkAddressBalanceHistory, nil}, @@ -187,13 +189,13 @@ func addRoutes(hs *handlers.HandlerService, publicRouter, internalRouter *mux.Ro {http.MethodGet, "/networks/{network}/transactions", hs.PublicGetNetworkTransactions, nil}, {http.MethodGet, "/networks/{network}/transactions/{hash}", hs.PublicGetNetworkTransaction, nil}, {http.MethodGet, "/networks/{network}/addresses/{address}/transactions", hs.PublicGetNetworkAddressTransactions, nil}, - {http.MethodGet, "/networks/{network}/slots/{slot}/transactions", hs.PublicGetNetworkSlotTransactions, nil}, + {http.MethodGet, "/networks/{network}/slots/{slot}/transactions", hs.PublicGetNetworkSlotTransactions, hs.InternalGetSlotTransactions}, {http.MethodGet, "/networks/{network}/blocks/{block}/transactions", hs.PublicGetNetworkBlockTransactions, hs.InternalGetBlockTransactions}, {http.MethodGet, "/networks/{network}/blocks/{block}/blobs", hs.PublicGetNetworkBlockBlobs, hs.InternalGetBlockBlobs}, {http.MethodGet, "/networks/{network}/handlerService-changes", hs.PublicGetNetworkBlsChanges, nil}, {http.MethodGet, "/networks/{network}/epochs/{epoch}/handlerService-changes", hs.PublicGetNetworkEpochBlsChanges, nil}, - {http.MethodGet, "/networks/{network}/slots/{slot}/handlerService-changes", hs.PublicGetNetworkSlotBlsChanges, nil}, + {http.MethodGet, "/networks/{network}/slots/{slot}/handlerService-changes", hs.PublicGetNetworkSlotBlsChanges, hs.InternalGetSlotBlsChanges}, {http.MethodGet, "/networks/{network}/blocks/{block}/handlerService-changes", hs.PublicGetNetworkBlockBlsChanges, hs.InternalGetBlockBlsChanges}, {http.MethodGet, "/networks/{network}/validators/{validator}/handlerService-changes", hs.PublicGetNetworkValidatorBlsChanges, nil}, From 189f0be913333d2610d4d980cca2523aa52ff339 Mon Sep 17 00:00:00 2001 From: remoterami Date: Thu, 1 Aug 2024 10:20:26 +0200 Subject: [PATCH 14/15] removed duplicate fields --- backend/pkg/api/types/block.go | 12 ++---------- frontend/types/api/block.ts | 12 ++---------- 2 files changed, 4 insertions(+), 20 deletions(-) diff --git a/backend/pkg/api/types/block.go b/backend/pkg/api/types/block.go index 5b3d071c2..3f3bae56c 100644 --- a/backend/pkg/api/types/block.go +++ b/backend/pkg/api/types/block.go @@ -18,22 +18,13 @@ type BlockSummary struct { type InternalGetBlockResponse ApiDataResponse[BlockSummary] type BlockExecutionPayload struct { - Block uint64 `json:"block"` BlockHash Hash `json:"block_hash"` ParentHash Hash `json:"parent_hash"` PriorityFeesRecipient Address `json:"priority_fees_recipient"` - PriorityFees decimal.Decimal `json:"priority_fees"` GasUsed uint64 `json:"gas_used"` GasLimit uint64 `json:"gas_limit"` BaseFeePerGas decimal.Decimal `json:"base_fee_per_gas"` BaseFees decimal.Decimal `json:"base_fees"` - Transactions struct { - General uint64 `json:"general"` - Blob uint64 `json:"blob"` - } `json:"transactions"` - Time int64 `json:"time"` - ExtraData string `json:"extra_data,omitempty"` - Graffiti string `json:"graffiti"` } type BlockConsensusLayer struct { @@ -49,6 +40,7 @@ type BlockConsensusLayer struct { Deposits uint64 `json:"deposit"` SyncCommittee BlockSyncCommittee `json:"sync_committee"` Eth1Data BlockEth1Data `json:"eth1_data"` + Graffiti string `json:"graffiti"` } type BlockSyncCommittee struct { @@ -114,7 +106,7 @@ type BlockOverview struct { Transactions *struct { General uint64 `json:"general"` Internal uint64 `json:"internal"` - Blob uint64 `json:"blob"` + Blob uint64 `json:"blob,omitempty"` } `json:"transactions,omitempty"` BlockRoot Hash `json:"block_root,omitempty"` ParentRoot Hash `json:"parent_root,omitempty"` diff --git a/frontend/types/api/block.ts b/frontend/types/api/block.ts index d3d5bf74d..56b0ff31b 100644 --- a/frontend/types/api/block.ts +++ b/frontend/types/api/block.ts @@ -19,22 +19,13 @@ export interface BlockSummary { } export type InternalGetBlockResponse = ApiDataResponse; export interface BlockExecutionPayload { - block: number /* uint64 */; block_hash: Hash; parent_hash: Hash; priority_fees_recipient: Address; - priority_fees: string /* decimal.Decimal */; gas_used: number /* uint64 */; gas_limit: number /* uint64 */; base_fee_per_gas: string /* decimal.Decimal */; base_fees: string /* decimal.Decimal */; - transactions: { - general: number /* uint64 */; - blob: number /* uint64 */; - }; - time: number /* int64 */; - extra_data?: string; - graffiti: string; } export interface BlockConsensusLayer { state_root: Hash; @@ -49,6 +40,7 @@ export interface BlockConsensusLayer { deposit: number /* uint64 */; sync_committee: BlockSyncCommittee; eth1_data: BlockEth1Data; + graffiti: string; } export interface BlockSyncCommittee { participation: number /* float64 */; @@ -116,7 +108,7 @@ export interface BlockOverview { transactions?: { general: number /* uint64 */; internal: number /* uint64 */; - blob: number /* uint64 */; + blob?: number /* uint64 */; }; block_root?: Hash; parent_root?: Hash; From ca52a7bb3c1f6c601c54b3548484690213e09d19 Mon Sep 17 00:00:00 2001 From: Thibaut <150015231+thib-wien@users.noreply.github.com> Date: Thu, 1 Aug 2024 16:24:16 +0200 Subject: [PATCH 15/15] (BIDS-3256) Login and Signup pages - redesign (#656) --- frontend/components/bc/PageWrapper.vue | 7 +- frontend/components/bc/header/HeaderLogo.vue | 88 +++++++++ frontend/components/bc/header/MainHeader.vue | 100 +++++------ frontend/i18n/en.json | 30 ++-- frontend/middleware/redirect.global.ts | 3 + frontend/pages/login.vue | 178 +++++++++++-------- frontend/pages/register.vue | 119 ++++++------- frontend/types/header.ts | 3 +- 8 files changed, 312 insertions(+), 216 deletions(-) create mode 100644 frontend/components/bc/header/HeaderLogo.vue diff --git a/frontend/components/bc/PageWrapper.vue b/frontend/components/bc/PageWrapper.vue index 610eae0bf..69221b0fb 100644 --- a/frontend/components/bc/PageWrapper.vue +++ b/frontend/components/bc/PageWrapper.vue @@ -1,11 +1,14 @@