mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-20 21:34:46 +00:00
Implement POST validators/validator_balances APIs (#4872)
* Add POST for fetching validators from state * Implement POST for balances * Tests
This commit is contained in:
@@ -317,6 +317,18 @@ impl BeaconNodeHttpClient {
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
async fn post_with_opt_response<T: Serialize, U: IntoUrl, R: DeserializeOwned>(
|
||||
&self,
|
||||
url: U,
|
||||
body: &T,
|
||||
) -> Result<Option<R>, Error> {
|
||||
if let Some(response) = self.post_generic(url, body, None).await.optional()? {
|
||||
response.json().await.map_err(Into::into)
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
/// Perform a HTTP POST request with a custom timeout.
|
||||
async fn post_with_timeout<T: Serialize, U: IntoUrl>(
|
||||
&self,
|
||||
@@ -524,6 +536,29 @@ impl BeaconNodeHttpClient {
|
||||
self.get_opt(path).await
|
||||
}
|
||||
|
||||
/// `POST beacon/states/{state_id}/validator_balances`
|
||||
///
|
||||
/// Returns `Ok(None)` on a 404 error.
|
||||
pub async fn post_beacon_states_validator_balances(
|
||||
&self,
|
||||
state_id: StateId,
|
||||
ids: Vec<ValidatorId>,
|
||||
) -> Result<Option<ExecutionOptimisticFinalizedResponse<Vec<ValidatorBalanceData>>>, Error>
|
||||
{
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||
.push("beacon")
|
||||
.push("states")
|
||||
.push(&state_id.to_string())
|
||||
.push("validator_balances");
|
||||
|
||||
let request = ValidatorBalancesRequestBody { ids };
|
||||
|
||||
self.post_with_opt_response(path, &request).await
|
||||
}
|
||||
|
||||
/// `GET beacon/states/{state_id}/validators?id,status`
|
||||
///
|
||||
/// Returns `Ok(None)` on a 404 error.
|
||||
@@ -563,6 +598,29 @@ impl BeaconNodeHttpClient {
|
||||
self.get_opt(path).await
|
||||
}
|
||||
|
||||
/// `POST beacon/states/{state_id}/validators`
|
||||
///
|
||||
/// Returns `Ok(None)` on a 404 error.
|
||||
pub async fn post_beacon_states_validators(
|
||||
&self,
|
||||
state_id: StateId,
|
||||
ids: Option<Vec<ValidatorId>>,
|
||||
statuses: Option<Vec<ValidatorStatus>>,
|
||||
) -> Result<Option<ExecutionOptimisticFinalizedResponse<Vec<ValidatorData>>>, Error> {
|
||||
let mut path = self.eth_path(V1)?;
|
||||
|
||||
path.path_segments_mut()
|
||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||
.push("beacon")
|
||||
.push("states")
|
||||
.push(&state_id.to_string())
|
||||
.push("validators");
|
||||
|
||||
let request = ValidatorsRequestBody { ids, statuses };
|
||||
|
||||
self.post_with_opt_response(path, &request).await
|
||||
}
|
||||
|
||||
/// `GET beacon/states/{state_id}/committees?slot,index,epoch`
|
||||
///
|
||||
/// Returns `Ok(None)` on a 404 error.
|
||||
|
||||
@@ -278,17 +278,18 @@ pub struct FinalityCheckpointsData {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(try_from = "&str")]
|
||||
#[serde(into = "String")]
|
||||
#[serde(try_from = "std::borrow::Cow<str>")]
|
||||
pub enum ValidatorId {
|
||||
PublicKey(PublicKeyBytes),
|
||||
Index(u64),
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for ValidatorId {
|
||||
impl TryFrom<std::borrow::Cow<'_, str>> for ValidatorId {
|
||||
type Error = String;
|
||||
|
||||
fn try_from(s: &str) -> Result<Self, Self::Error> {
|
||||
Self::from_str(s)
|
||||
fn try_from(s: std::borrow::Cow<str>) -> Result<Self, Self::Error> {
|
||||
Self::from_str(&s)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,6 +318,12 @@ impl fmt::Display for ValidatorId {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ValidatorId> for String {
|
||||
fn from(id: ValidatorId) -> String {
|
||||
id.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct ValidatorData {
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
@@ -492,6 +499,15 @@ pub struct ValidatorsQuery {
|
||||
pub status: Option<Vec<ValidatorStatus>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct ValidatorsRequestBody {
|
||||
#[serde(default)]
|
||||
pub ids: Option<Vec<ValidatorId>>,
|
||||
#[serde(default)]
|
||||
pub statuses: Option<Vec<ValidatorStatus>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct CommitteeData {
|
||||
#[serde(with = "serde_utils::quoted_u64")]
|
||||
@@ -656,6 +672,12 @@ pub struct ValidatorBalancesQuery {
|
||||
pub id: Option<Vec<ValidatorId>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct ValidatorBalancesRequestBody {
|
||||
pub ids: Vec<ValidatorId>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct BlobIndicesQuery {
|
||||
@@ -1879,3 +1901,20 @@ pub struct BlobsBundle<E: EthSpec> {
|
||||
#[serde(with = "ssz_types::serde_utils::list_of_hex_fixed_vec")]
|
||||
pub blobs: BlobsList<E>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn validator_id_serde() {
|
||||
let id_str = "\"1\"";
|
||||
let x: ValidatorId = serde_json::from_str(id_str).unwrap();
|
||||
assert_eq!(x, ValidatorId::Index(1));
|
||||
assert_eq!(serde_json::to_string(&x).unwrap(), id_str);
|
||||
|
||||
let pubkey_str = "\"0xb824b5ede33a7b05a378a84b183b4bc7e7db894ce48b659f150c97d359edca2f503081d6678d1200f582ec7cafa9caf2\"";
|
||||
let y: ValidatorId = serde_json::from_str(pubkey_str).unwrap();
|
||||
assert_eq!(serde_json::to_string(&y).unwrap(), pubkey_str);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user