-
Notifications
You must be signed in to change notification settings - Fork 209
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
chore(node-api): Validator balance endpoints - WIP #2483
base: main
Are you sure you want to change the base?
Changes from all commits
1ac13b4
58bdc83
642bf9a
900f949
f34d3c2
8546aee
93efc2a
8f31ecb
a357bc6
08064f7
fcb400f
b631d7d
b8ed978
2808857
4075c81
cd5ff6b
12c2ad2
3d8ba19
73e1d39
6cc0d18
029b554
2ec847b
4ed7c83
e8af248
55030da
c1b0563
c6e2408
de5a3ce
1c778e0
17a4ee0
b5ab7e9
dbf1da5
6cf51bc
fc34ae9
c42abb7
35c98be
2bbebed
4822ea9
07cc2eb
2207ca1
9177278
1b98570
705df2d
2c226ce
78f539c
9030c28
f4f7d6b
2dd0c9f
6014859
88cf482
c07010a
c78fac6
136f981
423fd5e
cdfaf85
7f25981
247ae34
823680e
640fefb
b0f7f33
d6ca21f
734d6b1
da9a476
fc266c8
7b1bfc1
e5037b9
1b523c9
0d4bad2
6438669
38e4fdf
dbe5cf1
735fe5d
f604b4f
7d992b9
e57bb36
1c3ef84
77c6b39
56f2814
64d4375
386aebd
4a63d72
14c7bef
13e584c
e944e8f
aa62ef1
b0b15c5
9e88e56
b78d051
973a645
23bed52
d1094e0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,6 +24,7 @@ import ( | |
"slices" | ||
"strconv" | ||
|
||
"cosmossdk.io/collections" | ||
"github.com/berachain/beacon-kit/consensus-types/types" | ||
"github.com/berachain/beacon-kit/errors" | ||
"github.com/berachain/beacon-kit/node-api/backend/utils" | ||
|
@@ -33,6 +34,9 @@ import ( | |
statedb "github.com/berachain/beacon-kit/state-transition/core/state" | ||
) | ||
|
||
// ErrValidatorNotFound is an error for when a validator is not found. | ||
var ErrValidatorNotFound = errors.New("validator not found") | ||
|
||
// ErrStatusFilterMismatch is an error for when a validator status does not | ||
// match the status filter. | ||
var ErrStatusFilterMismatch = errors.New("validator status does not match status filter") | ||
|
@@ -200,11 +204,21 @@ func (b Backend) ValidatorByID( | |
return nil, errors.Wrapf(err, "failed to get state from slot %d", slot) | ||
} | ||
index, err := utils.ValidatorIndexByID(st, id) | ||
if err != nil { | ||
switch { | ||
case err == nil: | ||
// continue processing | ||
case errors.Is(err, collections.ErrNotFound): | ||
return nil, ErrValidatorNotFound | ||
default: | ||
return nil, errors.Wrapf(err, "failed to get validator index by id %s", id) | ||
} | ||
validator, err := st.ValidatorByIndex(index) | ||
if err != nil { | ||
switch { | ||
case err == nil: | ||
// continue processing | ||
case errors.Is(err, collections.ErrNotFound): | ||
return nil, ErrValidatorNotFound | ||
default: | ||
return nil, errors.Wrapf(err, "failed to get validator by index %d", index) | ||
} | ||
balance, err := st.GetBalance(index) | ||
|
@@ -228,21 +242,49 @@ func (b Backend) ValidatorByID( | |
func (b Backend) ValidatorBalancesByIDs( | ||
slot math.Slot, ids []string, | ||
) ([]*beacontypes.ValidatorBalanceData, error) { | ||
var index math.U64 | ||
st, _, err := b.stateFromSlot(slot) | ||
if err != nil { | ||
return nil, errors.Wrapf(err, "failed to get state from slot %d", slot) | ||
} | ||
|
||
// If no IDs provided, return all validator balances | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what are the specs here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
if len(ids) == 0 { | ||
rawBalances, errInBalances := st.GetBalances() | ||
if errInBalances != nil { | ||
return nil, errInBalances | ||
} | ||
// Convert []uint64 to []*ValidatorBalanceData as per the API spec | ||
balances := make([]*beacontypes.ValidatorBalanceData, len(rawBalances)) | ||
for i, balance := range rawBalances { | ||
balances[i] = &beacontypes.ValidatorBalanceData{ | ||
Index: uint64(i), // #nosec:G115 // Safe as i comes from range loop | ||
Balance: balance, | ||
} | ||
} | ||
return balances, nil | ||
} | ||
|
||
balances := make([]*beacontypes.ValidatorBalanceData, 0) | ||
var index math.U64 | ||
|
||
for _, id := range ids { | ||
index, err = utils.ValidatorIndexByID(st, id) | ||
if err != nil { | ||
// If public key as id is not found in the state, do not return an error. | ||
if errors.Is(err, collections.ErrNotFound) { | ||
continue | ||
} | ||
return nil, errors.Wrapf(err, "failed to get validator index by id %s", id) | ||
} | ||
var balance math.U64 | ||
// TODO: same issue as above, shouldn't error on not found. | ||
balance, err = st.GetBalance(index) | ||
|
||
if err != nil { | ||
// if index does not exist and GetBalance returns an error containing "collections: not found" | ||
// do not return an error. | ||
if errors.Is(err, collections.ErrNotFound) { | ||
continue | ||
} | ||
return nil, errors.Wrapf(err, "failed to get validator balance for validator index %d", index) | ||
} | ||
balances = append(balances, &beacontypes.ValidatorBalanceData{ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
// | ||
// Copyright (C) 2025, Berachain Foundation. All rights reserved. | ||
// Use of this software is governed by the Business Source License included | ||
// in the LICENSE file of this repository and at www.mariadb.com/bsl11. | ||
// | ||
// ANY USE OF THE LICENSED WORK IN VIOLATION OF THIS LICENSE WILL AUTOMATICALLY | ||
// TERMINATE YOUR RIGHTS UNDER THIS LICENSE FOR THE CURRENT AND ALL OTHER | ||
// VERSIONS OF THE LICENSED WORK. | ||
// | ||
// THIS LICENSE DOES NOT GRANT YOU ANY RIGHT IN ANY TRADEMARK OR LOGO OF | ||
// LICENSOR OR ITS AFFILIATES (PROVIDED THAT YOU MAY USE A TRADEMARK OR LOGO OF | ||
// LICENSOR AS EXPRESSLY REQUIRED BY THIS LICENSE). | ||
// | ||
// TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON | ||
// AN “AS IS” BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, | ||
// EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF | ||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND | ||
// TITLE. | ||
|
||
package handlers | ||
|
||
// HTTPError represents an HTTP error response. | ||
type HTTPError struct { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we may have this already in our codebase? cc @rezbera |
||
Code int `json:"code"` | ||
Message string `json:"message"` | ||
} | ||
|
||
// NewHTTPError creates a new HTTPError. | ||
func NewHTTPError(code int, message string) *HTTPError { | ||
return &HTTPError{ | ||
Code: code, | ||
Message: message, | ||
} | ||
} | ||
|
||
// Error implements the error interface. | ||
func (e *HTTPError) Error() string { | ||
return e.Message | ||
} | ||
|
||
// StatusCode returns the HTTP status code. | ||
func (e *HTTPError) StatusCode() int { | ||
return e.Code | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you don't need to special case here?
Index may not exist but if it exists the validator must exist.
So here you can just