From 2c06a3bf433ef32ce10ac693b391f9e7038147f4 Mon Sep 17 00:00:00 2001 From: Joseph Livesey Date: Thu, 28 Nov 2024 11:32:50 -0500 Subject: [PATCH] chore: extract client to own repo --- Cargo.lock | 25 +- crates/firehose-client/CHANGELOG.md | 8 - crates/firehose-client/Cargo.toml | 27 -- crates/firehose-client/README.md | 80 ----- .../firehose-client/examples/fetch_beacon.rs | 61 ---- .../examples/fetch_ethereum.rs | 24 -- .../firehose-client/examples/stream_beacon.rs | 35 --- .../examples/stream_ethereum.rs | 34 -- crates/firehose-client/src/client.rs | 293 ------------------ crates/firehose-client/src/error.rs | 20 -- crates/firehose-client/src/lib.rs | 58 ---- crates/firehose-client/src/tls.rs | 20 -- 12 files changed, 2 insertions(+), 683 deletions(-) delete mode 100644 crates/firehose-client/CHANGELOG.md delete mode 100644 crates/firehose-client/Cargo.toml delete mode 100644 crates/firehose-client/README.md delete mode 100644 crates/firehose-client/examples/fetch_beacon.rs delete mode 100644 crates/firehose-client/examples/fetch_ethereum.rs delete mode 100644 crates/firehose-client/examples/stream_beacon.rs delete mode 100644 crates/firehose-client/examples/stream_ethereum.rs delete mode 100644 crates/firehose-client/src/client.rs delete mode 100644 crates/firehose-client/src/error.rs delete mode 100644 crates/firehose-client/src/lib.rs delete mode 100644 crates/firehose-client/src/tls.rs diff --git a/Cargo.lock b/Cargo.lock index 10e0570b..aee83724 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2158,27 +2158,6 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" -[[package]] -name = "firehose-client" -version = "0.1.1" -dependencies = [ - "dotenvy", - "firehose-protos", - "forrestrie", - "futures", - "hex", - "http", - "once_cell", - "rustls", - "serde", - "serde_derive", - "thiserror 2.0.3", - "tokio", - "tokio-stream", - "tonic", - "tracing", -] - [[package]] name = "firehose-client" version = "0.1.1" @@ -2231,7 +2210,7 @@ name = "firehose-protos-examples" version = "0.1.1" dependencies = [ "alloy-primitives 0.8.13", - "firehose-client 0.1.1 (git+https://github.com/semiotic-ai/firehose-client.git?branch=main)", + "firehose-client", "firehose-protos", "tokio", ] @@ -2365,7 +2344,7 @@ dependencies = [ "ethereum_ssz 0.7.1", "ethereum_ssz_derive 0.7.1", "ethportal-api", - "firehose-client 0.1.1 (git+https://github.com/semiotic-ai/firehose-client.git?branch=main)", + "firehose-client", "firehose-protos", "forrestrie", "futures", diff --git a/crates/firehose-client/CHANGELOG.md b/crates/firehose-client/CHANGELOG.md deleted file mode 100644 index 2e302c2f..00000000 --- a/crates/firehose-client/CHANGELOG.md +++ /dev/null @@ -1,8 +0,0 @@ -# Changelog - -## [0.1.1](https://github.com/semiotic-ai/veemon/compare/firehose-client-v0.1.0...firehose-client-v0.1.1) (2024-10-22) - - -### Bug Fixes - -* **firehose-client:** fix chain specification in client ([a37c8e8](https://github.com/semiotic-ai/veemon/commit/a37c8e81d20075c0980e50a039cb580bcaaa85d1)) diff --git a/crates/firehose-client/Cargo.toml b/crates/firehose-client/Cargo.toml deleted file mode 100644 index d0fa4f11..00000000 --- a/crates/firehose-client/Cargo.toml +++ /dev/null @@ -1,27 +0,0 @@ -[package] -name = "firehose-client" -version = "0.1.1" -edition = "2021" - -[lib] -name = "firehose_client" -path = "src/lib.rs" - -[dependencies] -dotenvy.workspace = true -forrestrie = { path = "../forrestrie" } -firehose-protos = { path = "../firehose-protos" } -futures.workspace = true -http.workspace = true -once_cell.workspace = true -rustls.workspace = true -serde = { workspace = true, features = ["derive"] } -serde_derive.workspace = true -thiserror.workspace = true -tokio = { workspace = true, features = ["macros", "rt-multi-thread"] } -tokio-stream.workspace = true -tonic = { workspace = true, features = ["tls-roots"] } -tracing.workspace = true - -[dev-dependencies] -hex.workspace = true diff --git a/crates/firehose-client/README.md b/crates/firehose-client/README.md deleted file mode 100644 index d860b723..00000000 --- a/crates/firehose-client/README.md +++ /dev/null @@ -1,80 +0,0 @@ -# Firehose Rust Client - -Extract blocks from [StreamingFast Firehose](https://firehose.streamingfast.io/) -programatically in Rust. - -## gRPC Endpoints - -### Env Vars - -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 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 - -### proto files - -We use the following protobuffers developed by Streamingfast via our -[`firehose-protos` crate](./../firehose-protos/README.md): - -See the [`firehose-protos` docs](./../firehose-protos/README.md) for information -on these protobuffers and links to the different repos that they've come from. - -Also check out [`forrestrie`](./../forrestrie/protos/README.md) for -Rust-compiled protobuffer Beacon block implementations. - -### gRPC Service Examples - -If you're looking to quickly explore what the Firehose API offers, -you can use the `grpcurl` tool to test your connection, verify your -API token, and get a list of available gRPC services. This is a great -way to interact with the API without writing any code. - -To get started, you can run the following command to retrieve the -service descriptions from the Firehose gRPC server: - -```bash -grpcurl -plaintext : describe -``` - -Below is an example of the service descriptions you might see when -querying the Firehose server: - -```terminal -grpc.health.v1.Health is a service: -service Health { - rpc Check ( .grpc.health.v1.HealthCheckRequest ) returns ( .grpc.health.v1.HealthCheckResponse ); - rpc Watch ( .grpc.health.v1.HealthCheckRequest ) returns ( stream .grpc.health.v1.HealthCheckResponse ); -} - -grpc.reflection.v1.ServerReflection is a service: -service ServerReflection { - rpc ServerReflectionInfo ( stream .grpc.reflection.v1.ServerReflectionRequest ) returns ( stream .grpc.reflection.v1.ServerReflectionResponse ); -} - -grpc.reflection.v1alpha.ServerReflection is a service: -service ServerReflection { - rpc ServerReflectionInfo ( stream .grpc.reflection.v1alpha.ServerReflectionRequest ) returns ( stream .grpc.reflection.v1alpha.ServerReflectionResponse ); -} - -sf.firehose.v1.Stream is a service: -service Stream { - rpc Blocks ( .sf.firehose.v1.Request ) returns ( stream .sf.firehose.v1.Response ); -} - -sf.firehose.v2.Fetch is a service: -service Fetch { - rpc Block ( .sf.firehose.v2.SingleBlockRequest ) returns ( .sf.firehose.v2.SingleBlockResponse ); -} - -sf.firehose.v2.Stream is a service: -service Stream { - rpc Blocks ( .sf.firehose.v2.Request ) returns ( stream .sf.firehose.v2.Response ); -} -``` diff --git a/crates/firehose-client/examples/fetch_beacon.rs b/crates/firehose-client/examples/fetch_beacon.rs deleted file mode 100644 index 41585298..00000000 --- a/crates/firehose-client/examples/fetch_beacon.rs +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2024-, Semiotic AI, Inc. -// SPDX-License-Identifier: Apache-2.0 - -//! # Fetch Beacon Block -//! -//! Demonstrates how to fetch a single block from Beacon Firehose, using the `Fetch` API. - -use firehose_client::{Chain, FirehoseClient}; -use firehose_protos::EthBlock; -use forrestrie::beacon_v1::{block::Body, Block as BeaconBlock}; - -#[tokio::main] -async fn main() { - // Show matching data from execution layer and beacon chain - let mut execution_layer_client = FirehoseClient::new(Chain::Ethereum); - - let response = execution_layer_client - .fetch_block(20672593) - .await - .unwrap() - .unwrap(); - - let block = EthBlock::try_from(response.into_inner()).unwrap(); - - assert_eq!(block.number, 20672593); - assert_eq!( - format!("0x{}", hex::encode(block.hash)).as_str(), - "0xea48ba1c8e38ea586239e9c5ec62949ddd79404c6006c099bb02a8b22ddd18e4" - ); - - let mut beacon_client = FirehoseClient::new(Chain::Beacon); - // This is the slot number for the Beacon block we want to fetch, but right now - // we don't have a way to map the block number of the execution block to the slot number - // of the Beacon block. - let response = beacon_client.fetch_block(9881091).await.unwrap().unwrap(); - let block = BeaconBlock::try_from(response.into_inner()).unwrap(); - - assert_eq!(block.slot, 9881091); - - let body = block.body.as_ref().unwrap(); - - match body { - Body::Deneb(body) => { - let execution_payload = body.execution_payload.as_ref().unwrap(); - - let block_hash = &execution_payload.block_hash; - - assert_eq!( - format!("0x{}", hex::encode(block_hash)).as_str(), - "0xea48ba1c8e38ea586239e9c5ec62949ddd79404c6006c099bb02a8b22ddd18e4" - ); - - let block_number = execution_payload.block_number; - - assert_eq!(block_number, 20672593); - } - _ => unimplemented!(), - }; - - println!("fetch_beacon ran to completion!"); -} diff --git a/crates/firehose-client/examples/fetch_ethereum.rs b/crates/firehose-client/examples/fetch_ethereum.rs deleted file mode 100644 index 09a7fd33..00000000 --- a/crates/firehose-client/examples/fetch_ethereum.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2024-, Semiotic AI, Inc. -// SPDX-License-Identifier: Apache-2.0 - -//! # Fetch Ethereum Block -//! -//! Demonstrates how to fetch a single block from Ethereum firehose. - -use firehose_client::{Chain, FirehoseClient}; -use firehose_protos::EthBlock as Block; - -#[tokio::main] -async fn main() { - let mut client = FirehoseClient::new(Chain::Ethereum); - let response = client.fetch_block(20672593).await.unwrap().unwrap(); - let block = Block::try_from(response.into_inner()).unwrap(); - - assert_eq!(block.number, 20672593); - assert_eq!( - format!("0x{}", hex::encode(block.hash)).as_str(), - "0xea48ba1c8e38ea586239e9c5ec62949ddd79404c6006c099bb02a8b22ddd18e4" - ); - - println!("fetch_beacon completed successfully!"); -} diff --git a/crates/firehose-client/examples/stream_beacon.rs b/crates/firehose-client/examples/stream_beacon.rs deleted file mode 100644 index 1d03b7f3..00000000 --- a/crates/firehose-client/examples/stream_beacon.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2024-, Semiotic AI, Inc. -// SPDX-License-Identifier: Apache-2.0 - -//! # Example: Stream Beacon Blocks -//! -//! Demonstrates how to stream a range of blocks from Firehose Beacon - -use firehose_client::{Chain, FirehoseClient}; -use forrestrie::beacon_v1::Block as FirehoseBeaconBlock; -use futures::StreamExt; - -#[tokio::main] -async fn main() { - // Testing this so far without proper benchmarking, the time taken to fetch the blocks - // grows linearly with the number of TOTAL_BLOCKS requested, to around 20 minutes for 8192 blocks! - const TOTAL_SLOTS: u64 = 100; - const START_SLOT: u64 = 9968872; - - let mut client = FirehoseClient::new(Chain::Beacon); - let mut stream = client - .stream_beacon_with_retry(START_SLOT, TOTAL_SLOTS) - .await - .unwrap(); - - let mut blocks: Vec = Vec::with_capacity(TOTAL_SLOTS as usize); - - while let Some(block) = stream.next().await { - blocks.push(block); - } - - // For now, just using this to signal that the test has completed - assert_eq!(blocks.len(), TOTAL_SLOTS as usize); - - println!("stream_beacon ran to completion!"); -} diff --git a/crates/firehose-client/examples/stream_ethereum.rs b/crates/firehose-client/examples/stream_ethereum.rs deleted file mode 100644 index 03c09f94..00000000 --- a/crates/firehose-client/examples/stream_ethereum.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2024-, Semiotic AI, Inc. -// SPDX-License-Identifier: Apache-2.0 - -//! # Example: Stream Ethereum Blocks -//! -//! This example demonstrates how to stream Ethereum blocks using the Firehose client. -use firehose_client::{Chain, FirehoseClient}; -use firehose_protos::EthBlock as Block; -use futures::StreamExt; - -#[tokio::main] -async fn main() { - // Testing this so far without proper benchmarking, the time taken to fetch the blocks - // grows linearly with the number of TOTAL_BLOCKS requested, to around 20 minutes for 8192 blocks! - const TOTAL_BLOCKS: u64 = 100; - const START_BLOCK: u64 = 19581798; - - let mut client = FirehoseClient::new(Chain::Ethereum); - let mut stream = client - .stream_blocks(START_BLOCK, TOTAL_BLOCKS) - .await - .unwrap(); - - let mut blocks: Vec = Vec::with_capacity(TOTAL_BLOCKS as usize); - - while let Some(block) = stream.next().await { - blocks.push(block); - } - - // For now, just using this to signal that the test has completed - assert_eq!(blocks.len(), TOTAL_BLOCKS as usize); - - println!("stream_ethereum ran successfully"); -} diff --git a/crates/firehose-client/src/client.rs b/crates/firehose-client/src/client.rs deleted file mode 100644 index 5a3ea566..00000000 --- a/crates/firehose-client/src/client.rs +++ /dev/null @@ -1,293 +0,0 @@ -// Copyright 2024-, Semiotic AI, Inc. -// SPDX-License-Identifier: Apache-2.0 - -use std::str::FromStr; - -use crate::error::ClientError; -use dotenvy::{dotenv, var}; -use firehose_protos::{ - EthBlock as Block, FetchClient, Request, SingleBlockRequest, SingleBlockResponse, StreamClient, -}; -use forrestrie::beacon_v1::Block as FirehoseBeaconBlock; -use tokio_stream::wrappers::ReceiverStream; -use tonic::{ - transport::{Channel, Uri}, - Response, Status, -}; -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>, - stream_client: Option>, -} - -impl FirehoseClient { - pub fn new(chain: Chain) -> Self { - Self { - chain, - fetch_client: None, - stream_client: None, - } - } - - /// The inner [`Result`] is the Firehose response, which can be either a [`Response`] or a [`Status`], - /// which is needed for handling empty slots on the Beacon chain. - pub async fn fetch_block( - &mut self, - number: u64, - ) -> Result, Status>, ClientError> { - if self.fetch_client.is_none() { - self.fetch_client = Some(fetch_client(self.chain).await?); - } - let mut request = create_single_block_fetch_request(number); - - request.insert_api_key_if_provided(self.chain); - - info!("Requesting block number:\n\t{}", number); - Ok(self.fetch_client.as_mut().unwrap().block(request).await) - } - - /// The tonic docs encourage cloning the client. - pub async fn get_streaming_client(&mut self) -> Result, ClientError> { - let client = if let Some(client) = self.stream_client.clone() { - client - } else { - self.stream_client = Some(stream_client(self.chain).await?); - self.stream_client.clone().unwrap() - }; - Ok(client) - } - - /// Stream a block range of Beacon blocks, with a retry mechanism if the stream cuts off - /// before the total number of blocks requested is reached, and accounting for missed slots. - pub async fn stream_beacon_with_retry( - &mut self, - start: u64, - total: u64, - ) -> Result, ClientError> { - let (tx, rx) = tokio::sync::mpsc::channel::(8192); - - let chain = self.chain; - let client = self.get_streaming_client().await?; - - tokio::spawn(async move { - let mut blocks = 0; - let mut last_valid_slot: Option = None; - let mut last_valid_block: Option = None; - - while blocks < total { - let mut client = client.clone(); - let request = create_blocks_streaming_request( - chain, - start + blocks, - start + total - 1, - BlocksRequested::All, - ); - match client.blocks(request).await { - Ok(response) => { - let mut stream_inner = response.into_inner(); - while let Ok(Some(block_msg)) = stream_inner.message().await { - if blocks % 100 == 0 { - trace!("Blocks fetched: {}", blocks); - } - match FirehoseBeaconBlock::try_from(block_msg) { - Ok(block) => { - if let Some(last_slot) = last_valid_slot { - let missed_slots = block.slot.saturating_sub(last_slot + 1); - if missed_slots > 0 { - trace!("Missed block at slot: {}", start + blocks); - - let last_block = last_valid_block.take().unwrap(); - let tx = tx.clone(); - for _ in 0..missed_slots { - blocks += 1; - tx.send(last_block.clone()).await.unwrap(); - } - } - } - last_valid_slot = Some(block.slot); - last_valid_block = Some(block.clone()); - - blocks += 1; - tx.clone().send(block).await.unwrap(); - } - Err(e) => { - error!("Failed to convert block message to block: {e}"); - break; - } - } - } - } - Err(e) => { - error!("Failed to get blocks stream: {:?}", e.code()); - break; - } - }; - } - }); - - Ok(ReceiverStream::new(rx)) - } - - pub async fn stream_blocks( - &mut self, - start: u64, - total: u64, - ) -> Result, ClientError> { - let (tx, rx) = tokio::sync::mpsc::channel::(8192); - - let chain = self.chain; - let client = self.get_streaming_client().await?; - - tokio::spawn(async move { - let mut blocks = 0; - - while blocks < total { - let mut client = client.clone(); - let request = create_blocks_streaming_request( - chain, - start + blocks, - start + total - 1, - BlocksRequested::All, - ); - let response = client.blocks(request).await.unwrap(); - let mut stream_inner = response.into_inner(); - while let Ok(Some(block_msg)) = stream_inner.message().await { - if blocks % 100 == 0 && blocks != 0 { - trace!("Blocks fetched: {}", blocks); - } - match Block::try_from(block_msg) { - Ok(block) => { - blocks += 1; - tx.clone().send(block).await.unwrap(); - } - Err(e) => { - panic!("Failed to convert block message to block: {e}"); - } - } - } - } - }); - - Ok(ReceiverStream::new(rx)) - } -} - -async fn build_and_connect_channel(uri: Uri) -> Result { - if uri.scheme_str() != Some("https") { - return Channel::builder(uri).connect().await; - } - - let config = crate::tls::config(); - - Channel::builder(uri) - .tls_config(config.clone())? - .connect() - .await -} - -fn create_blocks_streaming_request( - chain: Chain, - start_block_num: u64, - stop_block_num: u64, - blocks_requested: BlocksRequested, -) -> tonic::Request { - let mut request = tonic::Request::new(Request { - start_block_num: start_block_num as i64, - stop_block_num, - final_blocks_only: blocks_requested.into(), - ..Default::default() - }); - request.insert_api_key_if_provided(chain); - request -} - -async fn fetch_client(firehose: Chain) -> Result, ClientError> { - Ok(FetchClient::new({ - let uri = firehose.uri_from_env()?; - build_and_connect_channel(uri).await? - })) -} - -async fn stream_client(firehose: Chain) -> Result, ClientError> { - Ok(StreamClient::new({ - let uri = firehose.uri_from_env()?; - build_and_connect_channel(uri).await? - })) -} - -pub enum BlocksRequested { - All, - FinalOnly, -} - -impl From for bool { - fn from(blocks_requested: BlocksRequested) -> bool { - match blocks_requested { - BlocksRequested::All => false, - BlocksRequested::FinalOnly => true, - } - } -} - -/// Create a [`SingleBlockRequest`] for the given *number*. -/// Number is slot number for beacon blocks. -fn create_single_block_fetch_request(num: u64) -> tonic::Request { - tonic::Request::new(SingleBlockRequest::new(num)) -} - -trait FirehoseRequest { - fn insert_api_key_if_provided(&mut self, endpoint: Chain); -} - -impl FirehoseRequest for tonic::Request { - fn insert_api_key_if_provided(&mut self, endpoint: Chain) { - insert_api_key_if_provided(self, endpoint); - } -} - -fn insert_api_key_if_provided(request: &mut tonic::Request, chain: Chain) { - if let Ok(api_key) = var(chain.api_key_env_var_as_str()) { - let api_key_header = - tonic::metadata::MetadataValue::from_str(&api_key).expect("Invalid API key format"); - request.metadata_mut().insert("x-api-key", api_key_header); - } -} - -/// Extract blocks with [`FirehoseClient`] from an extendable union of chain variants. -#[derive(Clone, Copy, Debug)] -pub enum Chain { - Ethereum, - Beacon, - Arbitrum, -} - -impl Chain { - fn api_key_env_var_as_str(&self) -> &str { - match self { - Self::Beacon => "BEACON_API_KEY", - Self::Ethereum => "ETHEREUM_API_KEY", - Self::Arbitrum => "ARBITRUM_API_KEY", - } - } - - fn uri_from_env(&self) -> Result { - dotenv()?; - - let (url, port) = match self { - Self::Ethereum => ( - var("FIREHOSE_ETHEREUM_URL")?, - var("FIREHOSE_ETHEREUM_PORT")?, - ), - Self::Beacon => (var("FIREHOSE_BEACON_URL")?, var("FIREHOSE_BEACON_PORT")?), - Self::Arbitrum => ( - var("FIREHOSE_ARBITRUM_URL")?, - var("FIREHOSE_ARBITRUM_PORT")?, - ), - }; - - Ok(format!("{}:{}", url, port).parse::()?) - } -} diff --git a/crates/firehose-client/src/error.rs b/crates/firehose-client/src/error.rs deleted file mode 100644 index a1a8221f..00000000 --- a/crates/firehose-client/src/error.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2024-, Semiotic AI, Inc. -// SPDX-License-Identifier: Apache-2.0 - -use http::uri::InvalidUri; -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("{0}")] - TonicStatus(#[from] tonic::Status), - - #[error("Invalid URI: {0}")] - UriInvalid(#[from] InvalidUri), -} diff --git a/crates/firehose-client/src/lib.rs b/crates/firehose-client/src/lib.rs deleted file mode 100644 index 81710709..00000000 --- a/crates/firehose-client/src/lib.rs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2024-, Semiotic AI, Inc. -// SPDX-License-Identifier: Apache-2.0 - -//! # 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}; -//! # 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}; diff --git a/crates/firehose-client/src/tls.rs b/crates/firehose-client/src/tls.rs deleted file mode 100644 index 3faa2f66..00000000 --- a/crates/firehose-client/src/tls.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2024-, Semiotic AI, Inc. -// SPDX-License-Identifier: Apache-2.0 - -use once_cell::sync::Lazy; - -use tonic::transport::ClientTlsConfig; - -static TLS_CONFIG: Lazy = Lazy::new(|| { - rustls::crypto::ring::default_provider() - .install_default() - .expect("Failed to install rustls crypto provider"); - - ClientTlsConfig::new() - .with_native_roots() - .assume_http2(true) -}); - -pub fn config() -> &'static ClientTlsConfig { - &TLS_CONFIG -}