diff --git a/beacon-api-client/src/api_client.rs b/beacon-api-client/src/api_client.rs index 36e02ec38..e63feddf5 100644 --- a/beacon-api-client/src/api_client.rs +++ b/beacon-api-client/src/api_client.rs @@ -51,49 +51,32 @@ async fn api_error_or_value( } } -#[allow(clippy::type_complexity)] +pub trait ClientTypes { + type SignedContributionAndProof: serde::Serialize; + type SyncCommitteeContribution: serde::Serialize + serde::de::DeserializeOwned; + type BlindedBeaconBlock: serde::Serialize + serde::de::DeserializeOwned; + type SignedBlindedBeaconBlock: serde::Serialize + serde::de::DeserializeOwned; + type Attestation: serde::Serialize + serde::de::DeserializeOwned; + type AttesterSlashing: serde::Serialize + serde::de::DeserializeOwned; + type BeaconBlock: serde::Serialize + serde::de::DeserializeOwned; + type BeaconState: serde::Serialize + serde::de::DeserializeOwned; + type SignedAggregateAndProof: serde::Serialize; + type SignedBeaconBlock: serde::Serialize + serde::de::DeserializeOwned; + type BlobSidecar: serde::Serialize + serde::de::DeserializeOwned; + type LightClientBootstrap: serde::Serialize + serde::de::DeserializeOwned; + type LightClientUpdate: serde::Serialize + serde::de::DeserializeOwned; + type LightClientFinalityUpdate: serde::Serialize + serde::de::DeserializeOwned; + type LightClientOptimisticUpdate: serde::Serialize + serde::de::DeserializeOwned; +} + #[derive(Clone)] -pub struct Client { +pub struct Client { pub http: reqwest::Client, pub endpoint: Url, - _phantom: std::marker::PhantomData<(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O)>, + _phantom: std::marker::PhantomData, } -impl< - SignedContributionAndProof: serde::Serialize, - SyncCommitteeContribution: serde::Serialize + serde::de::DeserializeOwned, - BlindedBeaconBlock: serde::Serialize + serde::de::DeserializeOwned, - SignedBlindedBeaconBlock: serde::Serialize + serde::de::DeserializeOwned, - Attestation: serde::Serialize + serde::de::DeserializeOwned, - AttesterSlashing: serde::Serialize + serde::de::DeserializeOwned, - BeaconBlock: serde::Serialize + serde::de::DeserializeOwned, - BeaconState: serde::Serialize + serde::de::DeserializeOwned, - SignedAggregateAndProof: serde::Serialize, - SignedBeaconBlock: serde::Serialize + serde::de::DeserializeOwned, - BlobSidecar: serde::Serialize + serde::de::DeserializeOwned, - LightClientBootstrap: serde::Serialize + serde::de::DeserializeOwned, - LightClientUpdate: serde::Serialize + serde::de::DeserializeOwned, - LightClientFinalityUpdate: serde::Serialize + serde::de::DeserializeOwned, - LightClientOptimisticUpdate: serde::Serialize + serde::de::DeserializeOwned, - > - Client< - SignedContributionAndProof, - SyncCommitteeContribution, - BlindedBeaconBlock, - SignedBlindedBeaconBlock, - Attestation, - AttesterSlashing, - BeaconBlock, - BeaconState, - SignedAggregateAndProof, - SignedBeaconBlock, - BlobSidecar, - LightClientBootstrap, - LightClientUpdate, - LightClientFinalityUpdate, - LightClientOptimisticUpdate, - > -{ +impl Client { pub fn new_with_client>(client: reqwest::Client, endpoint: U) -> Self { Self { http: client, endpoint: endpoint.into(), _phantom: std::marker::PhantomData } } @@ -331,14 +314,14 @@ impl< pub async fn post_signed_blinded_beacon_block( &self, - block: &SignedBlindedBeaconBlock, + block: &C::SignedBlindedBeaconBlock, ) -> Result<(), Error> { self.post("eth/v1/beacon/blinded_blocks", block).await } pub async fn post_signed_blinded_beacon_block_v2( &self, - block: &SignedBlindedBeaconBlock, + block: &C::SignedBlindedBeaconBlock, broadcast_validation: Option, ) -> Result<(), Error> { let target = self.endpoint.join("eth/v2/beacon/blinded_blocks")?; @@ -350,13 +333,16 @@ impl< api_error_or_ok(response).await } - pub async fn post_signed_beacon_block(&self, block: &SignedBeaconBlock) -> Result<(), Error> { + pub async fn post_signed_beacon_block( + &self, + block: &C::SignedBeaconBlock, + ) -> Result<(), Error> { self.post("eth/v1/beacon/blocks", block).await } pub async fn post_signed_beacon_block_v2( &self, - block: &SignedBeaconBlock, + block: &C::SignedBeaconBlock, broadcast_validation: Option, ) -> Result<(), Error> { let target = self.endpoint.join("eth/v2/beacon/blocks")?; @@ -369,8 +355,8 @@ impl< } // v2 endpoint - pub async fn get_beacon_block(&self, id: BlockId) -> Result { - let result: VersionedValue = + pub async fn get_beacon_block(&self, id: BlockId) -> Result { + let result: VersionedValue = self.get(&format!("eth/v2/beacon/blocks/{id}")).await?; Ok(result.data) } @@ -383,8 +369,8 @@ impl< pub async fn get_attestations_from_beacon_block( &self, id: BlockId, - ) -> Result, Error> { - let result: Value> = + ) -> Result, Error> { + let result: Value> = self.get(&format!("eth/v1/beacon/blocks/{id}/attestations")).await?; Ok(result.data) } @@ -393,7 +379,7 @@ impl< &self, id: BlockId, indices: &[BlobIndex], - ) -> Result, Error> { + ) -> Result, Error> { let path = format!("eth/v1/beacon/blob_sidecars/{id}"); let target = self.endpoint.join(&path)?; let mut request = self.http.get(target); @@ -413,8 +399,11 @@ impl< Ok(result.data) } - pub async fn get_blinded_block(&self, id: BlockId) -> Result { - let result: VersionedValue = + pub async fn get_blinded_block( + &self, + id: BlockId, + ) -> Result { + let result: VersionedValue = self.get(&format!("eth/v1/beacon/blinded_blocks/{id}")).await?; Ok(result.data) } @@ -422,7 +411,7 @@ impl< pub async fn get_light_client_bootstrap( &self, block: Root, - ) -> Result { + ) -> Result { let result: Value<_> = self.get(&format!("eth/v1/beacon/light_client/bootstrap/{block}")).await?; Ok(result.data) @@ -432,7 +421,7 @@ impl< &self, start: u64, count: u64, - ) -> Result, Error> { + ) -> Result, Error> { let target = self.endpoint.join("eth/v1/beacon/light_client/updates")?; let mut request = self.http.get(target); request = request.query(&[("start_period", start), ("count", count)]); @@ -447,14 +436,14 @@ impl< pub async fn get_light_client_finality_update( &self, - ) -> Result { + ) -> Result { let result: Value<_> = self.get("eth/v1/beacon/light_client/finality_update").await?; Ok(result.data) } pub async fn get_light_client_optimistic_update( &self, - ) -> Result { + ) -> Result { let result: Value<_> = self.get("eth/v1/beacon/light_client/optimistic_update").await?; Ok(result.data) } @@ -463,7 +452,7 @@ impl< &self, slot: Option, committee_index: Option, - ) -> Result, Error> { + ) -> Result, Error> { let path = "eth/v1/beacon/pool/attestations"; let target = self.endpoint.join(path)?; let mut request = self.http.get(target); @@ -474,26 +463,28 @@ impl< request = request.query(&[("committee_index", committee_index)]); } let response = request.send().await?; - let result: ApiResult>> = response.json().await?; + let result: ApiResult>> = response.json().await?; match result { ApiResult::Ok(result) => Ok(result.data), ApiResult::Err(err) => Err(err.into()), } } - pub async fn post_attestations(&self, attestations: &[Attestation]) -> Result<(), Error> { + pub async fn post_attestations(&self, attestations: &[C::Attestation]) -> Result<(), Error> { self.post("eth/v1/beacon/pool/attestations", attestations).await } - pub async fn get_attester_slashings_from_pool(&self) -> Result, Error> { - let result: Value> = + pub async fn get_attester_slashings_from_pool( + &self, + ) -> Result, Error> { + let result: Value> = self.get("eth/v1/beacon/pool/attester_slashings").await?; Ok(result.data) } pub async fn post_attester_slashing( &self, - attester_slashing: &AttesterSlashing, + attester_slashing: &C::AttesterSlashing, ) -> Result<(), Error> { self.post("eth/v1/beacon/pool/attester_slashings", attester_slashing).await } @@ -585,8 +576,8 @@ impl< /* debug namespace */ // v2 endpoint - pub async fn get_state(&self, id: StateId) -> Result { - let result: VersionedValue = + pub async fn get_state(&self, id: StateId) -> Result { + let result: VersionedValue = self.get(&format!("eth/v2/debug/beacon/states/{id}")).await?; Ok(result.data) } @@ -715,7 +706,7 @@ impl< slot: Slot, randao_reveal: RandaoReveal, graffiti: Option, - ) -> Result { + ) -> Result { let path = format!("eth/v2/validator/blocks/{slot}"); let target = self.endpoint.join(&path)?; let mut request = self.http.get(target); @@ -724,7 +715,7 @@ impl< request = request.query(&[("graffiti", graffiti)]); } let response = request.send().await?; - let result: ApiResult> = response.json().await?; + let result: ApiResult> = response.json().await?; match result { ApiResult::Ok(result) => Ok(result.data), ApiResult::Err(err) => Err(err.into()), @@ -736,7 +727,7 @@ impl< slot: Slot, randao_reveal: RandaoReveal, graffiti: Option, - ) -> Result { + ) -> Result { let path = format!("eth/v1/validator/blinded_blocks/{slot}"); let target = self.endpoint.join(&path)?; let mut request = self.http.get(target); @@ -745,7 +736,7 @@ impl< request = request.query(&[("graffiti", graffiti)]); } let response = request.send().await?; - let result: ApiResult> = response.json().await?; + let result: ApiResult> = response.json().await?; match result { ApiResult::Ok(result) => Ok(result.data), ApiResult::Err(err) => Err(err.into()), @@ -773,13 +764,13 @@ impl< &self, attestation_data_root: Root, slot: Slot, - ) -> Result { + ) -> Result { let target = self.endpoint.join("eth/v1/validator/aggregate_attestation")?; let mut request = self.http.get(target); request = request.query(&[("attestation_data_root", attestation_data_root)]); request = request.query(&[("slot", slot)]); let response = request.send().await?; - let result: ApiResult> = response.json().await?; + let result: ApiResult> = response.json().await?; match result { ApiResult::Ok(result) => Ok(result.data), ApiResult::Err(err) => Err(err.into()), @@ -788,7 +779,7 @@ impl< pub async fn post_aggregates_with_proofs( &self, - aggregates_with_proofs: &[SignedAggregateAndProof], + aggregates_with_proofs: &[C::SignedAggregateAndProof], ) -> Result<(), Error> { self.post("eth/v1/validator/aggregate_and_proofs", aggregates_with_proofs).await } @@ -812,14 +803,14 @@ impl< slot: Slot, subcommittee_index: usize, beacon_block_root: Root, - ) -> Result { + ) -> Result { let target = self.endpoint.join("eth/v1/validator/sync_committee_contribution")?; let mut request = self.http.get(target); request = request.query(&[("slot", slot)]); request = request.query(&[("subcommittee_index", subcommittee_index)]); request = request.query(&[("beacon_block_root", beacon_block_root)]); let response = request.send().await?; - let result: ApiResult> = response.json().await?; + let result: ApiResult> = response.json().await?; match result { ApiResult::Ok(result) => Ok(result.data), ApiResult::Err(err) => Err(err.into()), @@ -828,7 +819,7 @@ impl< pub async fn post_sync_committee_contributions_with_proofs( &self, - contributions_with_proofs: &[SignedContributionAndProof], + contributions_with_proofs: &[C::SignedContributionAndProof], ) -> Result<(), Error> { self.post("eth/v1/validator/contribution_and_proofs", contributions_with_proofs).await } diff --git a/beacon-api-client/src/lib.rs b/beacon-api-client/src/lib.rs index 980bb1ad3..d27e6ee3b 100644 --- a/beacon-api-client/src/lib.rs +++ b/beacon-api-client/src/lib.rs @@ -43,23 +43,27 @@ pub mod presets { }, }; - pub type Client = crate::Client< - altair::SignedContributionAndProof, - altair::SyncCommitteeContribution, - BlindedBeaconBlock, - SignedBlindedBeaconBlock, - phase0::Attestation, - phase0::AttesterSlashing, - BeaconBlock, - BeaconState, - phase0::SignedAggregateAndProof, - SignedBeaconBlock, - deneb::BlobSidecar, - altair::LightClientBootstrap, - altair::LightClientUpdate, - altair::LightClientFinalityUpdate, - altair::LightClientOptimisticUpdate, - >; + pub struct MainnetClientTypes; + + impl crate::ClientTypes for MainnetClientTypes { + type SignedContributionAndProof = altair::SignedContributionAndProof; + type SyncCommitteeContribution = altair::SyncCommitteeContribution; + type BlindedBeaconBlock = BlindedBeaconBlock; + type SignedBlindedBeaconBlock = SignedBlindedBeaconBlock; + type Attestation = phase0::Attestation; + type AttesterSlashing = phase0::AttesterSlashing; + type BeaconBlock = BeaconBlock; + type BeaconState = BeaconState; + type SignedAggregateAndProof = phase0::SignedAggregateAndProof; + type SignedBeaconBlock = SignedBeaconBlock; + type BlobSidecar = deneb::BlobSidecar; + type LightClientBootstrap = altair::LightClientBootstrap; + type LightClientUpdate = altair::LightClientUpdate; + type LightClientFinalityUpdate = altair::LightClientFinalityUpdate; + type LightClientOptimisticUpdate = altair::LightClientOptimisticUpdate; + } + + pub type Client = crate::Client; } pub mod minimal { use ethereum_consensus::{ @@ -72,22 +76,26 @@ pub mod presets { }, }; - pub type Client = crate::Client< - altair::SignedContributionAndProof, - altair::SyncCommitteeContribution, - BlindedBeaconBlock, - SignedBlindedBeaconBlock, - phase0::Attestation, - phase0::AttesterSlashing, - BeaconBlock, - BeaconState, - phase0::SignedAggregateAndProof, - SignedBeaconBlock, - deneb::BlobSidecar, - altair::LightClientBootstrap, - altair::LightClientUpdate, - altair::LightClientFinalityUpdate, - altair::LightClientOptimisticUpdate, - >; + pub struct MinimalClientTypes; + + impl crate::ClientTypes for MinimalClientTypes { + type SignedContributionAndProof = altair::SignedContributionAndProof; + type SyncCommitteeContribution = altair::SyncCommitteeContribution; + type BlindedBeaconBlock = BlindedBeaconBlock; + type SignedBlindedBeaconBlock = SignedBlindedBeaconBlock; + type Attestation = phase0::Attestation; + type AttesterSlashing = phase0::AttesterSlashing; + type BeaconBlock = BeaconBlock; + type BeaconState = BeaconState; + type SignedAggregateAndProof = phase0::SignedAggregateAndProof; + type SignedBeaconBlock = SignedBeaconBlock; + type BlobSidecar = deneb::BlobSidecar; + type LightClientBootstrap = altair::LightClientBootstrap; + type LightClientUpdate = altair::LightClientUpdate; + type LightClientFinalityUpdate = altair::LightClientFinalityUpdate; + type LightClientOptimisticUpdate = altair::LightClientOptimisticUpdate; + } + + pub type Client = crate::Client; } }