fuel-streams 0.0.28

A library for working with streams of Fuel blockchain data
use reqwest::header::{
    CONNECTION,
    HOST,
    SEC_WEBSOCKET_KEY,
    SEC_WEBSOCKET_VERSION,
    UPGRADE,
};
use tokio_tungstenite::tungstenite::{
    client::IntoClientRequest,
    handshake::client::generate_key,
};

use super::{error::ClientError, Connection, ConnectionOpts};
use crate::FuelNetwork;

#[derive(Debug, Clone)]
pub struct Client {
    pub opts: ConnectionOpts,
}

impl Client {
    pub fn new(network: FuelNetwork) -> Self {
        Self {
            opts: ConnectionOpts {
                network,
                ..Default::default()
            },
        }
    }

    pub fn with_opts(opts: ConnectionOpts) -> Self {
        Self { opts }
    }

    pub fn with_api_key(&mut self, api_key: impl ToString) -> Self {
        Self {
            opts: ConnectionOpts {
                network: self.opts.network,
                api_key: Some(api_key.to_string()),
            },
        }
    }

    pub async fn connect(&mut self) -> Result<Connection, ClientError> {
        let api_key = self
            .opts
            .api_key
            .clone()
            .ok_or(ClientError::MissingApiKey)?;

        let subdirectory = format!("/api/v1/ws?api_key={}", api_key);
        let ws_url = self.opts.network.to_ws_url().join(&subdirectory)?;
        let host = ws_url
            .host_str()
            .ok_or_else(|| ClientError::HostParseFailed)?;

        let mut request = ws_url.as_str().into_client_request()?;
        let headers_map = request.headers_mut();
        headers_map.insert(HOST, host.parse()?);
        headers_map.insert(UPGRADE, "websocket".parse()?);
        headers_map.insert(CONNECTION, "Upgrade".parse()?);
        headers_map.insert(SEC_WEBSOCKET_KEY, generate_key().parse()?);
        headers_map.insert(SEC_WEBSOCKET_VERSION, "13".parse()?);
        Connection::new(request).await
    }
}