From 7eed713621cbbaa7a67a687fa52b60d0fd7c10e0 Mon Sep 17 00:00:00 2001 From: Marc Font <36164126+Marketen@users.noreply.github.com> Date: Fri, 12 Jan 2024 15:06:51 +0100 Subject: [PATCH] Add new api endpoint validatorsbyindex (#212) --- api/api.go | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++ api/types.go | 5 +++++ 2 files changed, 68 insertions(+) diff --git a/api/api.go b/api/api.go index 171d25a..a3cde29 100644 --- a/api/api.go +++ b/api/api.go @@ -61,6 +61,7 @@ const ( // Memory endpoints: what the oracle knows pathMemoryValidators = "/memory/validators" pathMemoryValidatorByIndex = "/memory/validator/{valindex}" + pathMemoryValidatorsByIndex = "/memory/validatorsbyindex/{valindices}" pathMemoryValidatorsByWithdrawal = "/memory/validators/{withdrawalAddress}" pathMemoryFeesInfo = "/memory/feesinfo" pathMemoryAllBlocks = "/memory/allblocks" @@ -195,6 +196,7 @@ func (m *ApiService) getRouter() http.Handler { // Memory endpoints r.HandleFunc(pathMemoryValidators, m.handleMemoryValidators).Methods(http.MethodGet) r.HandleFunc(pathMemoryValidatorByIndex, m.handleMemoryValidatorInfo).Methods(http.MethodGet) + r.HandleFunc(pathMemoryValidatorsByIndex, m.handleMemoryValidatorsByIndex).Methods(http.MethodGet) r.HandleFunc(pathMemoryValidatorsByWithdrawal, m.handleMemoryValidatorsByWithdrawal).Methods(http.MethodGet) r.HandleFunc(pathMemoryFeesInfo, m.handleMemoryFeesInfo).Methods(http.MethodGet) r.HandleFunc(pathMemoryPoolStatistics, m.handleMemoryStatistics).Methods(http.MethodGet) @@ -538,6 +540,66 @@ func (m *ApiService) handleMemoryValidatorInfo(w http.ResponseWriter, req *http. m.respondOK(w, validator) } +func (m *ApiService) handleMemoryValidatorsByIndex(w http.ResponseWriter, req *http.Request) { + vars := mux.Vars(req) + valIndicesStr := vars["valindices"] + + // Check if the string is empty or ends with a comma + if valIndicesStr == "" || strings.HasSuffix(valIndicesStr, ",") { + m.respondError(w, http.StatusBadRequest, "Invalid format for validator indices") + return + } + + // Split the valIndicesStr into a slice of strings + indicesStr := strings.Split(valIndicesStr, ",") + if len(indicesStr) > 100 { + m.respondError(w, http.StatusBadRequest, "Request exceeds maximum limit of 100 validators") + return + } + + // Check each index format and convert it to uint64 + var indices []uint64 + for _, indexStr := range indicesStr { + index, valid := IsValidIndex(indexStr) + if !valid { + m.respondError(w, http.StatusBadRequest, "Invalid format for validator indices") + return + } + indices = append(indices, index) + } + + // Initialize both response slices + var foundValidators []httpOkValidatorInfo + var notFoundValidators []uint64 + + // Check if each validator is in the oracle state. Append to foundValidators or notFoundValidators + for _, index := range indices { + if validator, found := m.oracle.State().Validators[index]; found { + // Convert ValidatorInfo to httpOkValidatorInfo. This is done to return strings instead of bigInts + foundValidator := httpOkValidatorInfo{ + ValidatorStatus: validator.ValidatorStatus.String(), + AccumulatedRewardsWei: validator.AccumulatedRewardsWei.String(), + PendingRewardsWei: validator.PendingRewardsWei.String(), + CollateralWei: validator.CollateralWei.String(), + WithdrawalAddress: validator.WithdrawalAddress, + ValidatorIndex: validator.ValidatorIndex, + ValidatorKey: validator.ValidatorKey, + SubscriptionType: validator.SubscriptionType.String(), + } + foundValidators = append(foundValidators, foundValidator) + } else { + notFoundValidators = append(notFoundValidators, index) + } + } + + response := httpOkValidatorsByIndex{ + Found: foundValidators, + NotFound: notFoundValidators, + } + + m.respondOK(w, response) +} + func (m *ApiService) handleMemoryValidatorsByWithdrawal(w http.ResponseWriter, req *http.Request) { if !m.OracleReady(MaxSlotsBehind) { m.respondError(w, http.StatusServiceUnavailable, "Oracle node is currently syncing and not serving requests") @@ -960,6 +1022,7 @@ func (m *ApiService) handleState(w http.ResponseWriter, req *http.Request) { m.respondOK(w, state) } +// Checks index and returns it as uint64 if valid func IsValidIndex(v string) (uint64, bool) { //re := regexp.MustCompile("^[0-9]+$") val, err := strconv.ParseUint(v, 10, 64) diff --git a/api/types.go b/api/types.go index c53343c..4518c35 100644 --- a/api/types.go +++ b/api/types.go @@ -140,6 +140,11 @@ type httpOkValidatorInfo struct { SubscriptionType string `json:"subscription_type"` } +type httpOkValidatorsByIndex struct { + Found []httpOkValidatorInfo `json:"found_validators"` + NotFound []uint64 `json:"not_found_validators"` +} + // Subscription event and the associated validator (if any) // TODO: Perhaps remove, no longer need if refactored a bit type Subscription struct { //TODO: remove