/*
 * Binance Derivatives Trading USDS Futures WebSocket Market Streams
 *
 * OpenAPI Specification for the Binance Derivatives Trading USDS Futures WebSocket Market Streams
 *
 * The version of the OpenAPI document: 1.0.0
 *
 *
 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 * https://openapi-generator.tech
 * Do not edit the class manually.
 */

#![allow(unused_imports)]
use serde_json::Value;
use std::sync::{Arc, atomic::Ordering};
use tokio::spawn;

use crate::common::config::ConfigurationWebsocketStreams;
use crate::common::websocket::{
    Subscription, WebsocketBase, WebsocketStream, WebsocketStreams as WebsocketStreamsBase,
    create_stream_handler,
};
use crate::models::{StreamId, WebsocketEvent, WebsocketMode};

mod apis;
mod handle;
mod models;

pub use apis::*;
pub use handle::*;
pub use models::*;

const HAS_TIME_UNIT: bool = false;

pub struct WebsocketStreams {
    websocket_streams_base: Arc<WebsocketStreamsBase>,
    market_api_client: MarketApiClient,
    public_api_client: PublicApiClient,
}

impl WebsocketStreams {
    pub(crate) async fn connect(
        config: ConfigurationWebsocketStreams,
        streams: Vec<String>,
        mode: Option<WebsocketMode>,
    ) -> anyhow::Result<Self> {
        let mut cfg = config;
        if let Some(m) = mode {
            cfg.mode = m;
        }

        if !HAS_TIME_UNIT {
            cfg.time_unit = None;
        }

        let websocket_streams_base = WebsocketStreamsBase::new(
            cfg,
            vec![],
            vec![
                "market".to_string(),
                "public".to_string(),
                "private".to_string(),
            ],
        );

        websocket_streams_base.clone().connect(streams).await?;

        Ok(Self {
            websocket_streams_base: websocket_streams_base.clone(),
            market_api_client: MarketApiClient::new(websocket_streams_base.clone()),
            public_api_client: PublicApiClient::new(websocket_streams_base.clone()),
        })
    }

    /// Subscribes to WebSocket events with a provided callback function.
    ///
    /// # Arguments
    ///
    /// * `callback` - A mutable function that takes a `WebsocketEvent` and is `Send` and `'static`.
    ///
    /// # Returns
    ///
    /// A `Subscription` that can be used to manage the event subscription.
    ///
    /// # Examples
    ///
    ///
    /// let subscription = `websocket_streams.subscribe_on_ws_events(|event`| {
    ///     // Handle WebSocket event
    /// });
    ///
    pub fn subscribe_on_ws_events<F>(&self, callback: F) -> Subscription
    where
        F: FnMut(WebsocketEvent) + Send + 'static,
    {
        let base = Arc::clone(&self.websocket_streams_base);
        base.common.events.subscribe(callback)
    }

    /// Unsubscribes from WebSocket events for a given `Subscription`.
    ///
    /// # Arguments
    ///
    /// * `subscription` - The `Subscription` to unsubscribe from WebSocket events.
    ///
    /// # Examples
    ///
    ///
    /// let subscription = `websocket_streams.subscribe_on_ws_events(|event`| {
    ///     // Handle WebSocket event
    /// });
    /// `websocket_streams.unsubscribe_from_ws_events(subscription)`;
    ///
    pub fn unsubscribe_from_ws_events(&self, subscription: Subscription) {
        subscription.unsubscribe();
    }

    /// Disconnects the WebSocket connection.
    ///
    /// # Returns
    ///
    /// A `Result` indicating whether the disconnection was successful.
    /// Returns an error if the disconnection fails.
    ///
    /// # Errors
    ///
    /// Returns an [`anyhow::Error`] if the connection fails.
    ///
    /// # Examples
    ///
    ///
    /// let `websocket_streams` = `WebSocketStreams::new`(...);
    /// `websocket_streams.disconnect().await`?;
    ///
    pub async fn disconnect(&self) -> anyhow::Result<()> {
        self.websocket_streams_base
            .disconnect()
            .await
            .map_err(anyhow::Error::msg)
    }

    /// Checks if the WebSocket connection is currently active.
    ///
    /// # Returns
    ///
    /// A `bool` indicating whether the WebSocket connection is established and connected.
    ///
    /// # Examples
    ///
    ///
    /// let `is_active` = `websocket_streams.is_connected().await`;
    /// if `is_active` {
    ///     // WebSocket connection is active
    /// }
    ///
    pub async fn is_connected(&self) -> bool {
        self.websocket_streams_base.is_connected().await
    }

    /// Sends a ping to the WebSocket server to maintain the connection.
    ///
    /// # Examples
    ///
    ///
    /// `websocket_streams.ping_server().await`;
    ///
    ///
    /// This method sends a ping request to the WebSocket server to keep the connection alive
    /// and check the server's responsiveness.
    pub async fn ping_server(&self) {
        self.websocket_streams_base.ping_server().await;
    }

    /// Subscribes to specified WebSocket streams.
    ///
    /// # Arguments
    ///
    /// * `streams` - A vector of stream names to subscribe to
    /// * `id` - An optional identifier for the subscription request
    ///
    /// # Examples
    ///
    ///
    /// `websocket_streams.subscribe(vec`!["`btcusdt@trade".to_string()`], None).await;
    ///
    ///
    /// This method initiates an asynchronous subscription to the specified WebSocket streams.
    /// The subscription is performed in a separate task using `spawn`.
    pub fn subscribe(&self, streams: Vec<String>, id: Option<String>) {
        let base = Arc::clone(&self.websocket_streams_base);
        spawn(async move { base.subscribe(streams, id.map(StreamId::from), None).await });
    }

    /// Unsubscribes from specified WebSocket streams.
    ///
    /// # Arguments
    ///
    /// * `streams` - A vector of stream names to unsubscribe from
    /// * `id` - An optional identifier for the unsubscription request
    ///
    /// # Examples
    ///
    ///
    /// `websocket_streams.unsubscribe(vec`!["`btcusdt@trade".to_string()`], None).await;
    ///
    ///
    /// This method initiates an asynchronous unsubscription from the specified WebSocket streams.
    /// The unsubscription is performed in a separate task using `spawn`.
    pub fn unsubscribe(&self, streams: Vec<String>, id: Option<String>) {
        let base = Arc::clone(&self.websocket_streams_base);
        spawn(async move {
            base.unsubscribe(streams, id.map(StreamId::from), None)
                .await;
        });
    }

    /// Checks if the current WebSocket stream is subscribed to a specific stream.
    ///
    /// # Arguments
    ///
    /// * `stream` - The name of the stream to check for subscription
    ///
    /// # Returns
    ///
    /// A boolean indicating whether the stream is currently subscribed
    ///
    /// # Examples
    ///
    ///
    /// let `is_subscribed` = `websocket_streams.is_subscribed("btcusdt@trade").await`;
    ///
    ///
    /// This method checks the subscription status of a specific WebSocket stream.
    pub async fn is_subscribed(&self, stream: &str) -> bool {
        self.websocket_streams_base.is_subscribed(stream).await
    }

    /// User Data Stream
    ///
    /// Establishes a WebSocket stream for user-specific data events.
    ///
    /// # Arguments
    ///
    /// - `listen_key`: A unique key for identifying the user's data stream
    /// - `id`: An optional identifier for the stream request
    ///
    /// # Returns
    ///
    /// [`Arc<WebsocketStream<UserDataStreamEventsResponse>>`] on success.
    ///
    /// # Errors
    ///
    /// Returns an [`anyhow::Error`] if the stream creation fails or if parsing the response encounters issues.
    ///
    /// # Examples
    ///
    ///
    /// let `user_stream` = `websocket_streams.user_data(listen_key`, None).await?;
    ///
    pub async fn user_data(
        &self,
        listen_key: String,
        id: Option<String>,
    ) -> anyhow::Result<Arc<WebsocketStream<UserDataStreamEventsResponse>>> {
        Ok(create_stream_handler::<UserDataStreamEventsResponse>(
            WebsocketBase::WebsocketStreams(self.websocket_streams_base.clone()),
            listen_key,
            id.map(StreamId::from),
            Some("private".to_string()),
        )
        .await)
    }

    /// Aggregate Trade Streams
    ///
    /// The Aggregate Trade Streams push market trade information that is aggregated for fills with same price and taking side every 100 milliseconds. Only market trades will be aggregated, which means the insurance fund trades and ADL trades won't be aggregated.
    ///
    /// Retail Price Improvement(RPI) orders are aggregated into field `q` and without special tags to be distinguished.
    ///
    /// Update Speed: 100ms
    ///
    /// # Arguments
    ///
    /// - `params`: [`AggregateTradeStreamsParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`Arc<WebsocketStream<models::AggregateTradeStreamsResponse>>`] on success.
    ///
    /// # Errors
    ///
    /// Returns an [`anyhow::Error`] if the stream request fails, if parameters are invalid, or if parsing the response fails.
    ///
    ///
    /// For full API details, see the [Binance API Documentation](https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Aggregate-Trade-Streams).
    ///
    pub async fn aggregate_trade_streams(
        &self,
        params: AggregateTradeStreamsParams,
    ) -> anyhow::Result<Arc<WebsocketStream<models::AggregateTradeStreamsResponse>>> {
        self.market_api_client.aggregate_trade_streams(params).await
    }

    /// All Market Liquidation Order Streams
    ///
    /// The All Liquidation Order Snapshot Streams push force liquidation order information for all symbols in the market.
    /// For each symbol，only the largest one liquidation order within 1000ms will be pushed as the snapshot. If no liquidation happens in the interval of 1000ms, no stream will be pushed.
    ///
    /// Update Speed: 1000ms
    ///
    /// # Arguments
    ///
    /// - `params`: [`AllMarketLiquidationOrderStreamsParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`Arc<WebsocketStream<models::AllMarketLiquidationOrderStreamsResponse>>`] on success.
    ///
    /// # Errors
    ///
    /// Returns an [`anyhow::Error`] if the stream request fails, if parameters are invalid, or if parsing the response fails.
    ///
    ///
    /// For full API details, see the [Binance API Documentation](https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/All-Market-Liquidation-Order-Streams).
    ///
    pub async fn all_market_liquidation_order_streams(
        &self,
        params: AllMarketLiquidationOrderStreamsParams,
    ) -> anyhow::Result<Arc<WebsocketStream<models::AllMarketLiquidationOrderStreamsResponse>>>
    {
        self.market_api_client
            .all_market_liquidation_order_streams(params)
            .await
    }

    /// All Market Mini Tickers Stream
    ///
    /// 24hr rolling window mini-ticker statistics for all symbols. These are NOT the statistics of the UTC day, but a 24hr rolling window from requestTime to 24hrs before. Note that only tickers that have changed will be present in the array.
    ///
    /// Update Speed: 1000ms
    ///
    /// # Arguments
    ///
    /// - `params`: [`AllMarketMiniTickersStreamParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`Arc<WebsocketStream<Vec<models::AllMarketMiniTickersStreamResponseInner>>>`] on success.
    ///
    /// # Errors
    ///
    /// Returns an [`anyhow::Error`] if the stream request fails, if parameters are invalid, or if parsing the response fails.
    ///
    ///
    /// For full API details, see the [Binance API Documentation](https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/All-Market-Mini-Tickers-Stream).
    ///
    pub async fn all_market_mini_tickers_stream(
        &self,
        params: AllMarketMiniTickersStreamParams,
    ) -> anyhow::Result<Arc<WebsocketStream<Vec<models::AllMarketMiniTickersStreamResponseInner>>>>
    {
        self.market_api_client
            .all_market_mini_tickers_stream(params)
            .await
    }

    /// All Market Tickers Streams
    ///
    /// 24hr rolling window ticker statistics for all symbols. These are NOT the statistics of the UTC day, but a 24hr rolling window from requestTime to 24hrs before. Note that only tickers that have changed will be present in the array.
    ///
    /// Update Speed: 1000ms
    ///
    /// # Arguments
    ///
    /// - `params`: [`AllMarketTickersStreamsParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`Arc<WebsocketStream<Vec<models::AllMarketTickersStreamsResponseInner>>>`] on success.
    ///
    /// # Errors
    ///
    /// Returns an [`anyhow::Error`] if the stream request fails, if parameters are invalid, or if parsing the response fails.
    ///
    ///
    /// For full API details, see the [Binance API Documentation](https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/All-Market-Tickers-Streams).
    ///
    pub async fn all_market_tickers_streams(
        &self,
        params: AllMarketTickersStreamsParams,
    ) -> anyhow::Result<Arc<WebsocketStream<Vec<models::AllMarketTickersStreamsResponseInner>>>>
    {
        self.market_api_client
            .all_market_tickers_streams(params)
            .await
    }

    /// Composite Index Symbol Information Streams
    ///
    /// Composite index information for index symbols pushed every second.
    ///
    /// Update Speed: 1000ms
    ///
    /// # Arguments
    ///
    /// - `params`: [`CompositeIndexSymbolInformationStreamsParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`Arc<WebsocketStream<models::CompositeIndexSymbolInformationStreamsResponse>>`] on success.
    ///
    /// # Errors
    ///
    /// Returns an [`anyhow::Error`] if the stream request fails, if parameters are invalid, or if parsing the response fails.
    ///
    ///
    /// For full API details, see the [Binance API Documentation](https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Composite-Index-Symbol-Information-Streams).
    ///
    pub async fn composite_index_symbol_information_streams(
        &self,
        params: CompositeIndexSymbolInformationStreamsParams,
    ) -> anyhow::Result<Arc<WebsocketStream<models::CompositeIndexSymbolInformationStreamsResponse>>>
    {
        self.market_api_client
            .composite_index_symbol_information_streams(params)
            .await
    }

    /// Continuous Contract Kline/Candlestick Streams
    ///
    ///
    /// Update Speed: 250ms
    ///
    /// # Arguments
    ///
    /// - `params`: [`ContinuousContractKlineCandlestickStreamsParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`Arc<WebsocketStream<models::ContinuousContractKlineCandlestickStreamsResponse>>`] on success.
    ///
    /// # Errors
    ///
    /// Returns an [`anyhow::Error`] if the stream request fails, if parameters are invalid, or if parsing the response fails.
    ///
    ///
    /// For full API details, see the [Binance API Documentation](https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Continuous-Contract-Kline-Candlestick-Streams).
    ///
    pub async fn continuous_contract_kline_candlestick_streams(
        &self,
        params: ContinuousContractKlineCandlestickStreamsParams,
    ) -> anyhow::Result<
        Arc<WebsocketStream<models::ContinuousContractKlineCandlestickStreamsResponse>>,
    > {
        self.market_api_client
            .continuous_contract_kline_candlestick_streams(params)
            .await
    }

    /// Contract Info Stream
    ///
    /// `ContractInfo` stream pushes when contract info updates(listing/settlement/contract bracket update). `bks` field only shows up when bracket gets updated.
    ///
    /// Update Speed: Real-time
    ///
    /// # Arguments
    ///
    /// - `params`: [`ContractInfoStreamParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`Arc<WebsocketStream<models::ContractInfoStreamResponse>>`] on success.
    ///
    /// # Errors
    ///
    /// Returns an [`anyhow::Error`] if the stream request fails, if parameters are invalid, or if parsing the response fails.
    ///
    ///
    /// For full API details, see the [Binance API Documentation](https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Contract-Info-Stream).
    ///
    pub async fn contract_info_stream(
        &self,
        params: ContractInfoStreamParams,
    ) -> anyhow::Result<Arc<WebsocketStream<models::ContractInfoStreamResponse>>> {
        self.market_api_client.contract_info_stream(params).await
    }

    /// Individual Symbol Mini Ticker Stream
    ///
    /// 24hr rolling window mini-ticker statistics for a single symbol. These are NOT the statistics of the UTC day, but a 24hr rolling window from requestTime to 24hrs before.
    ///
    /// Update Speed: 2s
    ///
    /// # Arguments
    ///
    /// - `params`: [`IndividualSymbolMiniTickerStreamParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`Arc<WebsocketStream<models::IndividualSymbolMiniTickerStreamResponse>>`] on success.
    ///
    /// # Errors
    ///
    /// Returns an [`anyhow::Error`] if the stream request fails, if parameters are invalid, or if parsing the response fails.
    ///
    ///
    /// For full API details, see the [Binance API Documentation](https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Individual-Symbol-Mini-Ticker-Stream).
    ///
    pub async fn individual_symbol_mini_ticker_stream(
        &self,
        params: IndividualSymbolMiniTickerStreamParams,
    ) -> anyhow::Result<Arc<WebsocketStream<models::IndividualSymbolMiniTickerStreamResponse>>>
    {
        self.market_api_client
            .individual_symbol_mini_ticker_stream(params)
            .await
    }

    /// Individual Symbol Ticker Streams
    ///
    /// 24hr rolling window ticker statistics for a single symbol. These are NOT the statistics of the UTC day, but a 24hr rolling window from requestTime to 24hrs before.
    ///
    /// Update Speed: 2000ms
    ///
    /// # Arguments
    ///
    /// - `params`: [`IndividualSymbolTickerStreamsParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`Arc<WebsocketStream<models::IndividualSymbolTickerStreamsResponse>>`] on success.
    ///
    /// # Errors
    ///
    /// Returns an [`anyhow::Error`] if the stream request fails, if parameters are invalid, or if parsing the response fails.
    ///
    ///
    /// For full API details, see the [Binance API Documentation](https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Individual-Symbol-Ticker-Streams).
    ///
    pub async fn individual_symbol_ticker_streams(
        &self,
        params: IndividualSymbolTickerStreamsParams,
    ) -> anyhow::Result<Arc<WebsocketStream<models::IndividualSymbolTickerStreamsResponse>>> {
        self.market_api_client
            .individual_symbol_ticker_streams(params)
            .await
    }

    /// Kline/Candlestick Streams
    ///
    /// The Kline/Candlestick Stream push updates to the current klines/candlestick every 250 milliseconds (if existing).
    ///
    /// Update Speed: 250ms
    ///
    /// # Arguments
    ///
    /// - `params`: [`KlineCandlestickStreamsParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`Arc<WebsocketStream<models::KlineCandlestickStreamsResponse>>`] on success.
    ///
    /// # Errors
    ///
    /// Returns an [`anyhow::Error`] if the stream request fails, if parameters are invalid, or if parsing the response fails.
    ///
    ///
    /// For full API details, see the [Binance API Documentation](https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Kline-Candlestick-Streams).
    ///
    pub async fn kline_candlestick_streams(
        &self,
        params: KlineCandlestickStreamsParams,
    ) -> anyhow::Result<Arc<WebsocketStream<models::KlineCandlestickStreamsResponse>>> {
        self.market_api_client
            .kline_candlestick_streams(params)
            .await
    }

    /// Liquidation Order Streams
    ///
    /// The Liquidation Order Snapshot Streams push force liquidation order information for specific symbol.
    /// For each symbol，only the largest one liquidation order within 1000ms will be pushed as the snapshot. If no liquidation happens in the interval of 1000ms, no stream will be pushed.
    ///
    /// Update Speed: 1000ms
    ///
    /// # Arguments
    ///
    /// - `params`: [`LiquidationOrderStreamsParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`Arc<WebsocketStream<models::LiquidationOrderStreamsResponse>>`] on success.
    ///
    /// # Errors
    ///
    /// Returns an [`anyhow::Error`] if the stream request fails, if parameters are invalid, or if parsing the response fails.
    ///
    ///
    /// For full API details, see the [Binance API Documentation](https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Liquidation-Order-Streams).
    ///
    pub async fn liquidation_order_streams(
        &self,
        params: LiquidationOrderStreamsParams,
    ) -> anyhow::Result<Arc<WebsocketStream<models::LiquidationOrderStreamsResponse>>> {
        self.market_api_client
            .liquidation_order_streams(params)
            .await
    }

    /// Mark Price Stream
    ///
    /// Mark price and funding rate for a single symbol pushed every 3 seconds or every second.
    ///
    /// Update Speed: 3000ms or 1000ms
    ///
    /// # Arguments
    ///
    /// - `params`: [`MarkPriceStreamParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`Arc<WebsocketStream<models::MarkPriceStreamResponse>>`] on success.
    ///
    /// # Errors
    ///
    /// Returns an [`anyhow::Error`] if the stream request fails, if parameters are invalid, or if parsing the response fails.
    ///
    ///
    /// For full API details, see the [Binance API Documentation](https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Mark-Price-Stream).
    ///
    pub async fn mark_price_stream(
        &self,
        params: MarkPriceStreamParams,
    ) -> anyhow::Result<Arc<WebsocketStream<models::MarkPriceStreamResponse>>> {
        self.market_api_client.mark_price_stream(params).await
    }

    /// Mark Price Stream for All market
    ///
    /// Mark price and funding rate for all symbols pushed every 3 seconds or every second.
    ///
    /// **Note**:
    ///
    /// `TradFi` symbols will be pushed through a seperate message.
    ///
    /// Update Speed: 3000ms or 1000ms
    ///
    /// # Arguments
    ///
    /// - `params`: [`MarkPriceStreamForAllMarketParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`Arc<WebsocketStream<Vec<models::MarkPriceStreamForAllMarketResponseInner>>>`] on success.
    ///
    /// # Errors
    ///
    /// Returns an [`anyhow::Error`] if the stream request fails, if parameters are invalid, or if parsing the response fails.
    ///
    ///
    /// For full API details, see the [Binance API Documentation](https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Mark-Price-Stream-for-All-market).
    ///
    pub async fn mark_price_stream_for_all_market(
        &self,
        params: MarkPriceStreamForAllMarketParams,
    ) -> anyhow::Result<Arc<WebsocketStream<Vec<models::MarkPriceStreamForAllMarketResponseInner>>>>
    {
        self.market_api_client
            .mark_price_stream_for_all_market(params)
            .await
    }

    /// Multi-Assets Mode Asset Index
    ///
    /// Asset index for multi-assets mode user
    ///
    /// Update Speed: 1s
    ///
    /// # Arguments
    ///
    /// - `params`: [`MultiAssetsModeAssetIndexParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`Arc<WebsocketStream<Vec<models::MultiAssetsModeAssetIndexResponseInner>>>`] on success.
    ///
    /// # Errors
    ///
    /// Returns an [`anyhow::Error`] if the stream request fails, if parameters are invalid, or if parsing the response fails.
    ///
    ///
    /// For full API details, see the [Binance API Documentation](https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Multi-Assets-Mode-Asset-Index).
    ///
    pub async fn multi_assets_mode_asset_index(
        &self,
        params: MultiAssetsModeAssetIndexParams,
    ) -> anyhow::Result<Arc<WebsocketStream<Vec<models::MultiAssetsModeAssetIndexResponseInner>>>>
    {
        self.market_api_client
            .multi_assets_mode_asset_index(params)
            .await
    }

    /// Trading Session Stream
    ///
    /// Trading session information for the underlying assets of `TradFi` Perpetual contracts—covering the U.S. equity market and the commodity market—is updated every second. Trading session information for different underlying markets is pushed in separate messages. Session types for the equity market include "`PRE_MARKET`", "REGULAR", "`AFTER_MARKET`", "OVERNIGHT", and "`NO_TRADING`". Session types for the commodity market include "REGULAR" and "`NO_TRADING`".
    ///
    /// Update Speed: 1s
    ///
    /// # Arguments
    ///
    /// - `params`: [`TradingSessionStreamParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`Arc<WebsocketStream<models::TradingSessionStreamResponse>>`] on success.
    ///
    /// # Errors
    ///
    /// Returns an [`anyhow::Error`] if the stream request fails, if parameters are invalid, or if parsing the response fails.
    ///
    ///
    /// For full API details, see the [Binance API Documentation](https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Trading-Session-Stream).
    ///
    pub async fn trading_session_stream(
        &self,
        params: TradingSessionStreamParams,
    ) -> anyhow::Result<Arc<WebsocketStream<models::TradingSessionStreamResponse>>> {
        self.market_api_client.trading_session_stream(params).await
    }

    /// All Book Tickers Stream
    ///
    /// Pushes any update to the best bid or ask's price or quantity in real-time for all symbols.
    ///
    /// Retail Price Improvement(RPI) orders are not visible and excluded in the response message.
    ///
    /// Update Speed: 5s
    ///
    /// # Arguments
    ///
    /// - `params`: [`AllBookTickersStreamParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`Arc<WebsocketStream<models::AllBookTickersStreamResponse>>`] on success.
    ///
    /// # Errors
    ///
    /// Returns an [`anyhow::Error`] if the stream request fails, if parameters are invalid, or if parsing the response fails.
    ///
    ///
    /// For full API details, see the [Binance API Documentation](https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/All-Book-Tickers-Stream).
    ///
    pub async fn all_book_tickers_stream(
        &self,
        params: AllBookTickersStreamParams,
    ) -> anyhow::Result<Arc<WebsocketStream<models::AllBookTickersStreamResponse>>> {
        self.public_api_client.all_book_tickers_stream(params).await
    }

    /// Diff. Book Depth Streams
    ///
    /// Bids and asks, pushed every 250 milliseconds, 500 milliseconds, 100 milliseconds (if existing)
    ///
    /// Retail Price Improvement(RPI) orders are not visible and excluded in the response message.
    ///
    /// Update Speed: 250ms, 500ms, 100ms
    ///
    /// # Arguments
    ///
    /// - `params`: [`DiffBookDepthStreamsParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`Arc<WebsocketStream<models::DiffBookDepthStreamsResponse>>`] on success.
    ///
    /// # Errors
    ///
    /// Returns an [`anyhow::Error`] if the stream request fails, if parameters are invalid, or if parsing the response fails.
    ///
    ///
    /// For full API details, see the [Binance API Documentation](https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Diff-Book-Depth-Streams).
    ///
    pub async fn diff_book_depth_streams(
        &self,
        params: DiffBookDepthStreamsParams,
    ) -> anyhow::Result<Arc<WebsocketStream<models::DiffBookDepthStreamsResponse>>> {
        self.public_api_client.diff_book_depth_streams(params).await
    }

    /// Individual Symbol Book Ticker Streams
    ///
    /// Pushes any update to the best bid or ask's price or quantity in real-time for a specified symbol.
    ///
    /// Retail Price Improvement(RPI) orders are not visible and excluded in the response message.
    ///
    /// Update Speed: Real-time
    ///
    /// # Arguments
    ///
    /// - `params`: [`IndividualSymbolBookTickerStreamsParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`Arc<WebsocketStream<models::IndividualSymbolBookTickerStreamsResponse>>`] on success.
    ///
    /// # Errors
    ///
    /// Returns an [`anyhow::Error`] if the stream request fails, if parameters are invalid, or if parsing the response fails.
    ///
    ///
    /// For full API details, see the [Binance API Documentation](https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Individual-Symbol-Book-Ticker-Streams).
    ///
    pub async fn individual_symbol_book_ticker_streams(
        &self,
        params: IndividualSymbolBookTickerStreamsParams,
    ) -> anyhow::Result<Arc<WebsocketStream<models::IndividualSymbolBookTickerStreamsResponse>>>
    {
        self.public_api_client
            .individual_symbol_book_ticker_streams(params)
            .await
    }

    /// Partial Book Depth Streams
    ///
    /// Top **<levels\>** bids and asks, Valid **<levels\>** are 5, 10, or 20.
    ///
    /// Retail Price Improvement(RPI) orders are not visible and excluded in the response message.
    ///
    /// Update Speed: 250ms, 500ms or 100ms
    ///
    /// # Arguments
    ///
    /// - `params`: [`PartialBookDepthStreamsParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`Arc<WebsocketStream<models::PartialBookDepthStreamsResponse>>`] on success.
    ///
    /// # Errors
    ///
    /// Returns an [`anyhow::Error`] if the stream request fails, if parameters are invalid, or if parsing the response fails.
    ///
    ///
    /// For full API details, see the [Binance API Documentation](https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Partial-Book-Depth-Streams).
    ///
    pub async fn partial_book_depth_streams(
        &self,
        params: PartialBookDepthStreamsParams,
    ) -> anyhow::Result<Arc<WebsocketStream<models::PartialBookDepthStreamsResponse>>> {
        self.public_api_client
            .partial_book_depth_streams(params)
            .await
    }

    /// RPI Diff. Book Depth Streams
    ///
    /// Bids and asks including RPI orders, pushed every 500 milliseconds
    ///
    /// RPI(Retail Price Improvement) orders are included and aggreated in the response message. When the quantity of a price level to be updated is equal to 0, it means either all quotations for this price have been filled/canceled, or the quantity of crossed RPI orders for this price are hidden
    ///
    /// Update Speed: 500ms
    ///
    /// # Arguments
    ///
    /// - `params`: [`RpiDiffBookDepthStreamsParams`]
    ///   The parameters for this operation.
    ///
    /// # Returns
    ///
    /// [`Arc<WebsocketStream<models::RpiDiffBookDepthStreamsResponse>>`] on success.
    ///
    /// # Errors
    ///
    /// Returns an [`anyhow::Error`] if the stream request fails, if parameters are invalid, or if parsing the response fails.
    ///
    ///
    /// For full API details, see the [Binance API Documentation](https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Diff-Book-Depth-Streams-RPI).
    ///
    pub async fn rpi_diff_book_depth_streams(
        &self,
        params: RpiDiffBookDepthStreamsParams,
    ) -> anyhow::Result<Arc<WebsocketStream<models::RpiDiffBookDepthStreamsResponse>>> {
        self.public_api_client
            .rpi_diff_book_depth_streams(params)
            .await
    }
}
