Skip to content
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

docs: refine rust docs for public api #59

Merged
merged 5 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions crates/firehose-client/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# Firehose Ethereum Rust Client
# Firehose Rust Client

Extract blocks from [StreamingFast Firehose](https://firehose.streamingfast.io/)
programatically in Rust.

## gRPC Endpoints

Expand All @@ -7,9 +10,11 @@
Use environment variables to provide Firehose Ethereum and Firehose
Beacon providers of your choice.

To do this, place a `.env` file in the root of `veemon`. See the
`.env.example` file in the root of this repository for what you'll need,
depending on your requirements.
To do this, place a `.env` file in the root of the `veemon` repository.
See the `.env.example` file, also in the root of this repository, for what
you'll need, depending on your requirements. You may have access to a
Firehose provider and/or may need to use a provider. For example, you can
use [Pinax](https://app.pinax.network/) as an endpoint provider.

## firehose-ethereum and firehose-beacon gRPC

Expand Down
2 changes: 1 addition & 1 deletion crates/firehose-client/examples/fetch_beacon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//!
//! Demonstrates how to fetch a single block from Beacon Firehose, using the `Fetch` API.

use firehose_client::client::{Chain, FirehoseClient};
use firehose_client::{Chain, FirehoseClient};
use firehose_protos::EthBlock;
use forrestrie::beacon_v1::{block::Body, Block as BeaconBlock};

Expand Down
2 changes: 1 addition & 1 deletion crates/firehose-client/examples/fetch_ethereum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//!
//! Demonstrates how to fetch a single block from Ethereum firehose.

use firehose_client::client::{Chain, FirehoseClient};
use firehose_client::{Chain, FirehoseClient};
use firehose_protos::EthBlock as Block;

#[tokio::main]
Expand Down
2 changes: 1 addition & 1 deletion crates/firehose-client/examples/stream_beacon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//!
//! Demonstrates how to stream a range of blocks from Firehose Beacon

use firehose_client::client::{Chain, FirehoseClient};
use firehose_client::{Chain, FirehoseClient};
use forrestrie::beacon_v1::Block as FirehoseBeaconBlock;
use futures::StreamExt;

Expand Down
4 changes: 2 additions & 2 deletions crates/firehose-client/examples/stream_ethereum.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! # Example: Stream Ethereum Blocks
//!
//! This example demonstrates how to stream Ethereum blocks using the Firehose client.
use firehose_client::client::{Chain, FirehoseClient};
use firehose_client::{Chain, FirehoseClient};
use firehose_protos::EthBlock as Block;
use futures::StreamExt;

Expand All @@ -14,7 +14,7 @@ async fn main() {

let mut client = FirehoseClient::new(Chain::Ethereum);
let mut stream = client
.stream_ethereum_with_retry(START_BLOCK, TOTAL_BLOCKS)
.stream_blocks(START_BLOCK, TOTAL_BLOCKS)
.await
.unwrap();

Expand Down
4 changes: 3 additions & 1 deletion crates/firehose-client/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use tonic::{
};
use tracing::{error, info, trace};

/// Work with the fetch and streaming APIs supported by [StreamingFast Firehose](https://firehose.streamingfast.io/).
pub struct FirehoseClient {
chain: Chain,
fetch_client: Option<FetchClient<Channel>>,
Expand Down Expand Up @@ -127,7 +128,7 @@ impl FirehoseClient {
Ok(ReceiverStream::new(rx))
}

pub async fn stream_ethereum_with_retry(
pub async fn stream_blocks(
&mut self,
start: u64,
total: u64,
Expand Down Expand Up @@ -252,6 +253,7 @@ fn insert_api_key_if_provided<T>(request: &mut tonic::Request<T>, chain: Chain)
}
}

/// Extract blocks with [`FirehoseClient`] from an extendable union of chain variants.
#[derive(Clone, Copy, Debug)]
pub enum Chain {
Ethereum,
Expand Down
12 changes: 6 additions & 6 deletions crates/firehose-client/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ use thiserror::Error;

#[derive(Debug, Error)]
pub enum ClientError {
#[error("Missing environment variable: {0}")]
EnvVarMissing(#[from] dotenvy::Error),

#[error("gRPC error: {0}")]
GRpc(#[from] tonic::transport::Error),

#[error("Invalid URI: {0}")]
InvalidUri(#[from] InvalidUri),

#[error("Missing environment variable: {0}")]
MissingEnvVar(#[from] dotenvy::Error),

#[error("{0}")]
TonicStatus(#[from] tonic::Status),

#[error("Invalid URI: {0}")]
UriInvalid(#[from] InvalidUri),
}
58 changes: 55 additions & 3 deletions crates/firehose-client/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,55 @@
pub mod client;
pub mod error;
pub mod tls;
//! # Rust Firehose Client
//!
//! Rust implementation of a client for the [StreamingFast Firehose](https://firehose.streamingfast.io/)
//! gRPC Fetch `Block` and Stream `Block`s APIs.
//!
//! ## Fetching an Ethereum Block
//!
//! ```no_run
//! # use firehose_client::{Chain, FirehoseClient};
pedrohba1 marked this conversation as resolved.
Show resolved Hide resolved
//! # use firehose_protos::EthBlock as Block;
//! # #[tokio::main]
//! # async fn main() -> Result<(), firehose_protos::ProtosError> {
//! let mut client = FirehoseClient::new(Chain::Ethereum);
//!
//! if let Some(response) = client.fetch_block(20672593).await.unwrap().ok() {
//! let block = Block::try_from(response.into_inner())?;
//! assert_eq!(block.number, 20672593);
//! assert_eq!(
//! format!("0x{}", hex::encode(block.hash)).as_str(),
//! "0xea48ba1c8e38ea586239e9c5ec62949ddd79404c6006c099bb02a8b22ddd18e4"
//! );
//! }
//! # Ok(())
//! # }
//! ```
//!
//! ## Streaming Ethereum Blocks
//!
//! ```no_run
//! # use firehose_client::{Chain, FirehoseClient};
//! # use futures::StreamExt;
//! # #[tokio::main]
//! # async fn main() -> Result<(), firehose_protos::ProtosError> {
//! const TOTAL_BLOCKS: u64 = 8192;
//! const START_BLOCK: u64 = 19581798;
//!
//! let mut client = FirehoseClient::new(Chain::Ethereum);
//! let mut stream = client
//! .stream_blocks(START_BLOCK, TOTAL_BLOCKS)
//! .await
//! .unwrap();
//!
//! while let Some(block) = stream.next().await {
//! // Do Something with the extracted stream of blocks.
//! }
//! # Ok(())
//! # }
//! ```
//!

mod client;
mod error;
mod tls;

pub use crate::client::{Chain, FirehoseClient};
5 changes: 1 addition & 4 deletions crates/firehose-protos-examples/examples/receipt_root.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
//! This example demonstrates how to calculate the receipts root of a block and
//! compare it to the receipts root in the block header.
//!
use alloy_primitives::FixedBytes;
use firehose_client::client::{Chain, FirehoseClient};
use firehose_client::{Chain, FirehoseClient};
use firehose_protos::EthBlock as Block;

const BLOCK_NUMBER: u64 = 20672593;
Expand Down
29 changes: 29 additions & 0 deletions crates/firehose-protos-examples/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//! # Firehose Protos Examples
pedrohba1 marked this conversation as resolved.
Show resolved Hide resolved
//!
//! Examples that use methods implemented on the Rust-compiled Firehose
//! protobuffer types from [Firehose Protos](../firehose_protos/index.html).
//!
//! ## Running Examples
//!
//! To run the examples, you need access to a Firehose provider for each chain from which you want
//! to extract data - an endpoint and an API key (if the latter is required).
//!
//! If you need access to a Firehose provider, we suggest using [Pinax](https://app.pinax.network/).
//!
//! Add your endpoint and API key to a `.env` file in the root of the repository. See `.env.examples` for
//! a configuration template.
//!
//! To run individual examples, use the following command:
//!
//! ```terminal
//! cargo run -p firehose-protos-examples --example <example_name>
//! ```
//!
//! So, for example, to run the `receipt_root` example:
//!
//! ```terminal
//! cargo run -p firehose-protos-examples --example receipt_root
//! ```
//!

#![deny(missing_docs)]
1 change: 1 addition & 0 deletions crates/firehose-protos/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ fn main() {
let mut config = Config::new();
config.type_attribute(".", "#[derive(serde::Serialize, serde::Deserialize)]");
config.type_attribute(".", "#[allow(clippy::enum_variant_names)]");
config.type_attribute(".", "#[allow(missing_docs)]");

// Map Google protobuf types to prost_wkt_types
config.extern_path(".google.protobuf.Any", "::prost_wkt_types::Any");
Expand Down
116 changes: 71 additions & 45 deletions crates/firehose-protos/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,81 +3,107 @@ use thiserror::Error;
/// Custom error variants for Verifiable Extraction protobuffer types.
#[derive(Error, Debug)]
pub enum ProtosError {
#[error("Block conversion error")]
BlockConversionError,

#[error("BLS error: {0}")]
Bls(String),

#[error("Error in decoding block: {0}")]
DecodeError(#[from] prost::DecodeError),

#[error("GraffitiInvalid")]
GraffitiInvalid,

/// Invalid access tuple storage key.
#[error("Invalid access tuple storage key: {0}")]
InvalidAccessTupleStorageKey(String),
AccessTupleStorageKeyInvalid(String),

/// Missing attestation data.
#[error("Null attestation data")]
AttestationDataMissing,

/// Invalid BigInt.
#[error("Invalid BigInt: {0}")]
InvalidBigInt(String),
BigIntInvalid(String),

#[error("Invalid log address: {0}")]
InvalidLogAddress(String),
/// Error converting protobuffer to block type.
#[error("Block conversion error")]
BlockConversionError,

#[error("Invalid log topic: {0}")]
InvalidLogTopic(String),
/// Converted block missing block header.
#[error("BlockHeaderMissing")]
BlockHeaderMissing,

#[error("Invalid trace signature {0:?} component: {1}")]
InvalidTraceSignature(String, String),
/// Block response missing block.
#[error("Null block field in block response")]
BlockMissingInResponse,

#[error("Invalid transaction receipt logs bloom: {0}")]
InvalidTransactionReceiptLogsBloom(String),
/// [BLS signature](https://en.wikipedia.org/wiki/BLS_digital_signature) error.
#[error("BLS error: {0}")]
Bls(String),

#[error("KzgCommitmentInvalid")]
KzgCommitmentInvalid,
/// Missing BLS to Execution Change
#[error("Null BlsToExecutionChange")]
BlsToExecutionChangeMissing,

#[error("MissingBlockHeader")]
MissingBlockHeader,
/// Checkpoint missing.
#[error("Null checkpoint")]
CheckpointMissing,

#[error("Null attestation data")]
NullAttestationData,
/// [prost] library decode error.
#[error("Error in decoding block: {0}")]
DecodeError(#[from] prost::DecodeError),

#[error("Null indexed attestation data")]
NullIndexedAttestationData,
/// Missing deposit data.
#[error("Null deposit data")]
DepositDataMissing,

#[error("Null block field in block response")]
NullBlock,
/// Missing execution payload.
#[error("Null execution payload")]
ExecutionPayloadMissing,

#[error("Null BlsToExecutionChange")]
NullBlsToExecutionChange,
/// Graffiti invalid when decoding block.
#[error("GraffitiInvalid")]
GraffitiInvalid,

#[error("Null checkpoint")]
NullCheckpoint,
/// Missing indexed attestation data.
#[error("Null indexed attestation data")]
IndexedAttestationDataMissing,

#[error("Null deposit data")]
NullDepositData,
/// Invalid KZG commitment.
#[error("KzgCommitmentInvalid")]
KzgCommitmentInvalid,

#[error("Null execution payload")]
NullExecutionPayload,
/// Invalid log address.
#[error("Invalid log address: {0}")]
LogAddressInvalid(String),

#[error("Proposer Slashing null signer")]
NullSigner,
/// Invalid log topic.
#[error("Invalid log topic: {0}")]
LogTopicInvalid(String),

/// Missing signed Beacon block header message.
#[error("Null SignedBeaconBlockHeader Message")]
NullSignedBeaconBlockHeaderMessage,
SignedBeaconBlockHeaderMessageMissing,

#[error("Null voluntary exit")]
NullVoluntaryExit,
/// Missing signer
#[error("Null signer")]
SignerMissing,

/// Invalid trace signature for ECDSA component.
#[error("Invalid trace signature {0:?} component: {1}")]
TraceSignatureInvalid(String, String),

/// SSZ Types error.
#[error("SSZ Types error: {0}")]
SszTypesError(String),

/// Transaction missing call.
#[error("Transaction missing call")]
TransactionMissingCall,

/// Invalid transaction receipt logs bloom.
#[error("Invalid transaction receipt logs bloom: {0}")]
TransactionReceiptLogsBloomInvalid(String),

/// Transaction trace missing receipt.
#[error("Transaction trace missing receipt")]
TransactionTraceMissingReceipt,

/// Transaction type conversion error.
#[error("TxTypeConversionError: {0}")]
TxTypeConversion(String),

/// Missing voluntary exit.
#[error("Null voluntary exit")]
VoluntaryExitMissing,
}
4 changes: 2 additions & 2 deletions crates/firehose-protos/src/ethereum_v2/access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ fn convert_to_b256(key: &Vec<u8>) -> Result<B256, ProtosError> {
let key_bytes: [u8; 32] = key
.as_slice()
.try_into()
.map_err(|_| ProtosError::InvalidAccessTupleStorageKey(hex::encode(key.clone())))?;
.map_err(|_| ProtosError::AccessTupleStorageKeyInvalid(hex::encode(key.clone())))?;
Ok(B256::from(key_bytes))
}

Expand Down Expand Up @@ -80,7 +80,7 @@ mod tests {

assert!(matches!(
error,
ProtosError::InvalidAccessTupleStorageKey(_)
ProtosError::AccessTupleStorageKeyInvalid(_)
));
}
}
Loading
Loading