diff --git a/Cargo.toml b/Cargo.toml index 3fe32881..64a6b8ea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,24 +19,25 @@ python = ["pyo3"] [dependencies] async-trait = "0.1" -base64 = "0.12.3" -chrono = { version = "0.4.11", features = ["std", "serde"] } -dotenv = "0.15.0" -futures = "0.3.5" -futures-util = "0.3.8" +base64 = "0.13" +chrono = { version = "0.4", features = ["std", "serde"] } +dotenv = "0.15" +futures = "0.3" +futures-util = "0.3" hex = "0.4.2" hmac = "0.8.1" log = "0.4.8" -reqwest = { version = "0.10", features = ["json", "blocking"] } +reqwest = { version = "0.11", features = ["json", "blocking"] } rust_decimal = "1.7.0" sugar = "0.2.0" -serde = { version = "1.0.114", features = ["derive"] } -serde_json = "1.0.55" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" serde_urlencoded = "0.6.1" thiserror = "1.0.20" -tokio = { version = "0.2", features = ["full"] } -tokio-tungstenite = { version = "0.10.1", features = ["tls"] } -tungstenite = "0.11.0" +tokio = { version = "1.0", features = ["full"] } +tokio-stream = "0.1" +tokio-tungstenite = { version = "0.13", features = ["tls"] } +tungstenite = "0.12" sha2 = "0.9.1" url = "2.1.1" derive_more = "0.99" diff --git a/src/coinbase/prelude.rs b/src/coinbase/prelude.rs index d6d188df..9ea37cc5 100644 --- a/src/coinbase/prelude.rs +++ b/src/coinbase/prelude.rs @@ -1 +1 @@ -pub type Result = std::result::Result; \ No newline at end of file +pub type Result = std::result::Result; diff --git a/src/errors.rs b/src/errors.rs index f15a8197..cf55cd62 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -97,4 +97,6 @@ pub enum OpenLimitsError { NotParsableResponse(String), #[error("")] MissingParameter(String), + #[error("")] + InvalidParameter(String), } diff --git a/src/model/mod.rs b/src/model/mod.rs index 9d9b7fe3..60adb618 100644 --- a/src/model/mod.rs +++ b/src/model/mod.rs @@ -157,6 +157,7 @@ pub struct CancelAllOrdersRequest { #[derive(Serialize, Deserialize, Clone, Constructor, Debug)] pub struct GetOrderHistoryRequest { pub market_pair: Option, + pub order_status: Option>, pub paginator: Option, } diff --git a/src/model/python.rs b/src/model/python.rs index 44ace6ba..626717c2 100644 --- a/src/model/python.rs +++ b/src/model/python.rs @@ -7,6 +7,7 @@ use crate::nash::{Environment, NashCredentials, NashParameters}; use pyo3::exceptions::PyException; use pyo3::prelude::{FromPyObject, IntoPy, PyObject, PyResult, Python, ToPyObject}; use pyo3::types::PyDict; +use std::time::Duration; // Python to Rust... @@ -199,12 +200,21 @@ impl<'a> FromPyObject<'a> for NashParameters { "timeout not included in nash credentials", ))? .extract()?; + let timeout = Duration::from_millis(timeout); + let sign_states_loop_interval: Option = py_dict + .get_item("timeout") + .ok_or(PyException::new_err( + "sign states loop interval not included in nash credentials", + ))? + .extract()?; + let sign_states_loop_interval = sign_states_loop_interval.map(Duration::from_millis); Ok(NashParameters { affiliate_code, credentials, client_id, environment, timeout, + sign_states_loop_interval, }) } } diff --git a/src/nash/mod.rs b/src/nash/mod.rs index f99ca429..f4ba830f 100644 --- a/src/nash/mod.rs +++ b/src/nash/mod.rs @@ -21,8 +21,7 @@ use crate::{ }; use async_trait::async_trait; use chrono::Utc; -pub use nash_native_client::ws_client::client::Client; -pub use nash_native_client::ws_client::client::Environment; +pub use nash_native_client::{Client, Environment}; use rust_decimal::prelude::*; use std::convert::{TryFrom, TryInto}; @@ -43,7 +42,7 @@ pub struct NashParameters { pub client_id: u64, pub environment: Environment, pub timeout: Duration, - pub sign_states_loop_interval: Option, + pub sign_states_loop_interval: Option, } impl Clone for NashParameters { @@ -64,33 +63,35 @@ impl Clone for NashParameters { } async fn client_from_params_failable(params: NashParameters) -> Result { - let out = match params.credentials { + let client = match params.credentials { Some(credentials) => { - Client::from_key_data( + Client::from_keys( &credentials.secret, &credentials.session, params.affiliate_code, params.client_id, params.environment, params.timeout, - params.sign_states_loop_interval, ) - .await + .await? } None => { - Client::new( + Client::from_keys_path( None, params.client_id, None, params.environment, params.timeout, - params.sign_states_loop_interval, ) - .await + .await? } }; - Ok(out.map_err(OpenLimitsError::NashProtocolError)?) + if let Some(interval) = params.sign_states_loop_interval { + client.start_background_state_signing(interval); + } + + Ok(client) } #[async_trait] @@ -113,7 +114,7 @@ impl Exchange for Nash { #[async_trait] impl ExchangeMarketData for Nash { async fn get_historic_rates(&self, req: &GetHistoricRatesRequest) -> Result> { - let req: nash_protocol::protocol::list_candles::ListCandlesRequest = req.into(); + let req: nash_protocol::protocol::list_candles::ListCandlesRequest = req.try_into()?; let resp = self.transport.run(req).await; @@ -159,13 +160,13 @@ impl ExchangeMarketData for Nash { impl ExchangeAccount for Nash { async fn cancel_all_orders(&self, req: &CancelAllOrdersRequest) -> Result> { let req: nash_protocol::protocol::cancel_all_orders::CancelAllOrders = req.into(); - self.transport.run(req).await?; + self.transport.run_http(req).await?; Ok(vec![]) } async fn cancel_order(&self, req: &CancelOrderRequest) -> Result { let req: nash_protocol::protocol::cancel_order::CancelOrderRequest = req.into(); - let resp = self.transport.run(req).await; + let resp = self.transport.run_http(req).await; Ok( Nash::unwrap_response::( resp, @@ -267,7 +268,7 @@ impl ExchangeAccount for Nash { let req: nash_protocol::protocol::place_order::LimitOrderRequest = Nash::convert_limit_order(req, nash_protocol::types::BuyOrSell::Buy); - let resp = self.transport.run(req).await; + let resp = self.transport.run_http(req).await; Ok( Nash::unwrap_response::( @@ -280,7 +281,7 @@ impl ExchangeAccount for Nash { async fn limit_sell(&self, req: &OpenLimitOrderRequest) -> Result { let req: nash_protocol::protocol::place_order::LimitOrderRequest = Nash::convert_limit_order(req, nash_protocol::types::BuyOrSell::Sell); - let resp = self.transport.run(req).await; + let resp = self.transport.run_http(req).await; Ok( Nash::unwrap_response::( @@ -294,7 +295,7 @@ impl ExchangeAccount for Nash { let req: nash_protocol::protocol::place_order::MarketOrderRequest = Nash::convert_market_request(req); - let resp = self.transport.run(req).await; + let resp = self.transport.run_http(req).await; Ok( Nash::unwrap_response::( resp, @@ -448,7 +449,7 @@ impl TryFrom<&TradeHistoryRequest> { type Error = OpenLimitsError; fn try_from(req: &TradeHistoryRequest) -> crate::shared::Result { - let (before, limit, range) = try_split_paginator(req.paginator.clone()); + let (before, limit, range) = try_split_paginator(req.paginator.clone())?; Ok(Self { market: req.market_pair.clone(), @@ -512,11 +513,14 @@ impl From for Liquidity { } } -impl From<&GetHistoricRatesRequest> for nash_protocol::protocol::list_candles::ListCandlesRequest { - fn from(req: &GetHistoricRatesRequest) -> Self { - let (before, limit, range) = try_split_paginator(req.paginator.clone()); +impl TryFrom<&GetHistoricRatesRequest> + for nash_protocol::protocol::list_candles::ListCandlesRequest +{ + type Error = OpenLimitsError; + fn try_from(req: &GetHistoricRatesRequest) -> crate::shared::Result { + let (before, limit, range) = try_split_paginator(req.paginator.clone())?; - Self { + Ok(Self { market: req.market_pair.clone(), chronological: None, before, @@ -527,25 +531,30 @@ impl From<&GetHistoricRatesRequest> for nash_protocol::protocol::list_candles::L ), limit, range, - } + }) } } fn try_split_paginator( paginator: Option, -) -> ( +) -> crate::shared::Result<( Option, Option, Option, -) { - match paginator { +)> { + Ok(match paginator { Some(paginator) => ( paginator.before, - paginator - .limit - .map(|v| i64::try_from(v).expect("Couldn't convert u64 to i64.")), + match paginator.limit { + Some(v) => Some(i64::try_from(v).map_err(|_| { + OpenLimitsError::InvalidParameter( + "Couldn't convert paginator limit to i64".to_string(), + ) + })?), + None => None, + }, if paginator.start_time.is_some() && paginator.end_time.is_some() { - Some(DateTimeRange { + Some(nash_protocol::types::DateTimeRange { start: paginator.start_time.map(timestamp_to_utc_datetime).unwrap(), stop: paginator.end_time.map(timestamp_to_utc_datetime).unwrap(), }) @@ -554,7 +563,7 @@ fn try_split_paginator( }, ), None => (None, None, None), - } + }) } impl TryFrom<&GetHistoricTradesRequest> @@ -563,7 +572,7 @@ impl TryFrom<&GetHistoricTradesRequest> type Error = OpenLimitsError; fn try_from(req: &GetHistoricTradesRequest) -> crate::shared::Result { let market = req.market_pair.clone(); - let (before, limit, _) = try_split_paginator(req.paginator.clone()); + let (before, limit, _) = try_split_paginator(req.paginator.clone())?; //FIXME: Some issues with the graphql protocol for the market to be non nil Ok(Self { market, @@ -624,7 +633,7 @@ impl TryFrom<&GetOrderHistoryRequest> { type Error = OpenLimitsError; fn try_from(req: &GetOrderHistoryRequest) -> crate::shared::Result { - let (before, limit, range) = try_split_paginator(req.paginator.clone()); + let (before, limit, range) = try_split_paginator(req.paginator.clone())?; Ok(Self { market: req.market_pair.clone(), @@ -633,7 +642,14 @@ impl TryFrom<&GetOrderHistoryRequest> range, buy_or_sell: None, order_type: None, - status: None, + status: match req.order_status.clone() { + Some(v) => Some( + v.into_iter() + .map(TryInto::try_into) + .collect::>>()?, + ), + None => None, + }, }) } } @@ -677,6 +693,23 @@ impl From for OrderStatus { } } +impl TryFrom for nash_protocol::types::OrderStatus { + type Error = OpenLimitsError; + fn try_from(status: OrderStatus) -> crate::shared::Result { + Ok(match status { + OrderStatus::Filled => nash_protocol::types::OrderStatus::Filled, + OrderStatus::Open => nash_protocol::types::OrderStatus::Open, + OrderStatus::Canceled => nash_protocol::types::OrderStatus::Canceled, + OrderStatus::Pending => nash_protocol::types::OrderStatus::Pending, + _ => { + return Err(OpenLimitsError::InvalidParameter( + "Had invalid order status for Nash".to_string(), + )) + } + }) + } +} + impl From<&GetPriceTickerRequest> for nash_protocol::protocol::get_ticker::TickerRequest { fn from(req: &GetPriceTickerRequest) -> Self { let market = req.market_pair.clone(); @@ -730,7 +763,6 @@ use nash_protocol::protocol::{ subscriptions::{SubscriptionRequest, SubscriptionResponse}, ResponseOrError, }; -use nash_protocol::types::DateTimeRange; use std::{pin::Pin, task::Context, task::Poll}; use tokio::time::Duration; @@ -738,50 +770,6 @@ pub struct NashWebsocket { pub client: Client, } -impl NashWebsocket { - pub async fn public( - client_id: u64, - environment: Environment, - timeout: Duration, - sign_states_loop_interval: Option, - ) -> Self { - NashWebsocket { - client: Client::new( - None, - client_id, - None, - environment, - timeout, - sign_states_loop_interval, - ) - .await - .expect("Couldn't create Client."), - } - } - - pub async fn with_credential( - secret: &str, - session: &str, - client_id: u64, - environment: Environment, - timeout: Duration, - sign_states_loop_interval: Option, - ) -> Result { - Client::from_key_data( - secret, - session, - None, - client_id, - environment, - timeout, - sign_states_loop_interval, - ) - .await - .map(|client| NashWebsocket { client }) - .map_err(OpenLimitsError::NashProtocolError) - } -} - impl Stream for NashWebsocket { type Item = std::result::Result< ResponseOrError, @@ -818,7 +806,7 @@ impl ExchangeWs for NashWebsocket { for subscription in subscriptions.into_iter() { let stream = self.client.subscribe_protocol(subscription).await?; - streams.push(stream); + streams.push(tokio_stream::wrappers::UnboundedReceiverStream::new(stream)); } let s = streams.map(|message| match message { diff --git a/tests/any_exchange/reconnection.rs b/tests/any_exchange/reconnection.rs index 64d7ba2c..86bec35a 100644 --- a/tests/any_exchange/reconnection.rs +++ b/tests/any_exchange/reconnection.rs @@ -1,4 +1,4 @@ -use nash_native_client::ws_client::client::Environment; +use nash_native_client::Environment; use openlimits::shared::Result; use openlimits::{model::websocket::Subscription, nash::NashWebsocket}; use tokio::time::Duration; @@ -43,21 +43,21 @@ async fn test_subscription_callback( .expect("Couldn't receive sync."); } -#[tokio::test(core_threads = 2)] +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn coinbase() { let client = init_coinbase().await; let sub = Subscription::OrderBookUpdates("BTC-USD".to_string()); test_subscription_callback(client.expect("Couldn't create client."), sub).await; } -#[tokio::test(core_threads = 2)] +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn nash() { let client = init_nash().await; let sub = Subscription::OrderBookUpdates("btc_usdc".to_string()); test_subscription_callback(client.expect("Couldn't create client."), sub).await; } -#[tokio::test(core_threads = 2)] +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn binance() { let client = init_binance().await; let sub = Subscription::OrderBookUpdates("bnbbtc".to_string()); diff --git a/tests/any_exchange/websocket.rs b/tests/any_exchange/websocket.rs index 170a135e..db7d42bd 100644 --- a/tests/any_exchange/websocket.rs +++ b/tests/any_exchange/websocket.rs @@ -3,14 +3,14 @@ // supported exchanges. use dotenv::dotenv; -use nash_native_client::ws_client::client::Environment; +use nash_native_client::Environment; use openlimits::any_exchange::{AnyExchange, AnyWsExchange}; use openlimits::binance::{Binance, BinanceCredentials, BinanceParameters}; use openlimits::coinbase::client::websocket::CoinbaseWebsocket; use openlimits::coinbase::{Coinbase, CoinbaseCredentials, CoinbaseParameters}; use openlimits::exchange::OpenLimits; use openlimits::exchange_ws::OpenLimitsWs; -use openlimits::nash::{Nash, NashCredentials, NashParameters, NashWebsocket}; +use openlimits::nash::{Nash, NashCredentials, NashParameters}; use openlimits::shared::Result; use std::env; use tokio::time::Duration; @@ -68,23 +68,6 @@ async fn init() -> Result { coinbase().await.map(|exchange| exchange.into()) } -async fn _nash_websocket() -> OpenLimitsWs { - dotenv().ok(); - - let websocket = NashWebsocket::with_credential( - &env::var("NASH_API_SECRET").unwrap(), - &env::var("NASH_API_KEY").unwrap(), - 1234, - Environment::Sandbox, - Duration::from_secs_f32(10.0), - None, - ) - .await - .expect("Couldn't connect."); - - OpenLimitsWs { websocket } -} - async fn coinbase_websocket() -> OpenLimitsWs { dotenv().ok(); diff --git a/tests/apis/binance/websocket.rs b/tests/apis/binance/websocket.rs index 0e513231..b376f092 100644 --- a/tests/apis/binance/websocket.rs +++ b/tests/apis/binance/websocket.rs @@ -21,63 +21,63 @@ async fn test_subscription_callback(websocket: BinanceWebsocket, sub: BinanceSub rx.recv().expect("Couldn't receive sync message."); } -#[tokio::test(core_threads = 2)] +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn aggregate_trade() { let websocket = init().await; let sub = BinanceSubscription::AggregateTrade("bnbbtc".to_string()); test_subscription_callback(websocket, sub).await; } -#[tokio::test(core_threads = 2)] +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn candlestick() { let websocket = init().await; let sub = BinanceSubscription::Candlestick("bnbbtc".to_string(), "1m".to_string()); test_subscription_callback(websocket, sub).await; } -#[tokio::test(core_threads = 2)] +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn depth() { let websocket = init().await; let sub = BinanceSubscription::Depth("bnbbtc".to_string(), Some(1)); test_subscription_callback(websocket, sub).await; } -#[tokio::test(core_threads = 2)] +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn mini_ticker() { let websocket = init().await; let sub = BinanceSubscription::MiniTicker("bnbbtc".to_string()); test_subscription_callback(websocket, sub).await; } -#[tokio::test(core_threads = 2)] +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn mini_ticker_all() { let websocket = init().await; let sub = BinanceSubscription::MiniTickerAll; test_subscription_callback(websocket, sub).await; } -#[tokio::test(core_threads = 2)] +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn order_book() { let websocket = init().await; let sub = BinanceSubscription::OrderBook("bnbbtc".to_string(), 10); test_subscription_callback(websocket, sub).await; } -#[tokio::test(core_threads = 2)] +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn ticker() { let websocket = init().await; let sub = BinanceSubscription::Ticker("bnbbtc".to_string()); test_subscription_callback(websocket, sub).await; } -#[tokio::test(core_threads = 2)] +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn ticker_all() { let websocket = init().await; let sub = BinanceSubscription::TickerAll; test_subscription_callback(websocket, sub).await; } -#[tokio::test(core_threads = 2)] +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn trade() { let websocket = init().await; let sub = BinanceSubscription::Trade("bnbbtc".to_string()); diff --git a/tests/apis/coinbase/websocket.rs b/tests/apis/coinbase/websocket.rs index f6b35aa4..1b2581a3 100644 --- a/tests/apis/coinbase/websocket.rs +++ b/tests/apis/coinbase/websocket.rs @@ -42,7 +42,7 @@ async fn test_subscription_callback( .expect("Couldn't receive sync message."); } -#[tokio::test(core_threads = 2)] +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn order_book() { let websocket = init().await; let sub = CoinbaseSubscription::Level2("BTC-USD".to_string()); diff --git a/tests/binance/account.rs b/tests/binance/account.rs index 7921573a..1b51e770 100644 --- a/tests/binance/account.rs +++ b/tests/binance/account.rs @@ -160,6 +160,7 @@ async fn get_order_history() { let exchange = init().await; let req = GetOrderHistoryRequest { market_pair: Some(String::from("BNBBTC")), + order_status: None, paginator: None, }; diff --git a/tests/binance/ws_callbacks.rs b/tests/binance/ws_callbacks.rs index 7cfbbbd9..d5c341b9 100644 --- a/tests/binance/ws_callbacks.rs +++ b/tests/binance/ws_callbacks.rs @@ -20,14 +20,14 @@ async fn test_subscription_callback(websocket: OpenLimitsWs, s rx.recv().expect("Couldn't receive sync message."); } -#[tokio::test(core_threads = 2)] +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn orderbook() { let ws = init().await; let sub = Subscription::OrderBookUpdates("bnbbtc".to_string()); test_subscription_callback(ws, sub).await; } -#[tokio::test(core_threads = 2)] +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn trades() { let ws = init().await; let sub = Subscription::Trades("btcusdt".to_string()); diff --git a/tests/binance/ws_streams.rs b/tests/binance/ws_streams.rs index 3f6ae385..dc033a0f 100644 --- a/tests/binance/ws_streams.rs +++ b/tests/binance/ws_streams.rs @@ -5,7 +5,7 @@ use openlimits::{ model::websocket::Subscription, }; -#[tokio::test(core_threads = 2)] +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn orderbook() { let ws = init().await; let s = ws @@ -17,7 +17,7 @@ async fn orderbook() { print!("{:?}", ob); } -#[tokio::test(core_threads = 2)] +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn trades() { let ws = init().await; let s = ws diff --git a/tests/coinbase/account.rs b/tests/coinbase/account.rs index a0681d3f..fa90b48d 100644 --- a/tests/coinbase/account.rs +++ b/tests/coinbase/account.rs @@ -153,6 +153,7 @@ async fn get_order_history() { let exchange = init().await; let req = GetOrderHistoryRequest { market_pair: Some(String::from("ETH-BTC")), + order_status: None, paginator: None, }; diff --git a/tests/nash/account.rs b/tests/nash/account.rs index 407c0196..e9d21d9d 100644 --- a/tests/nash/account.rs +++ b/tests/nash/account.rs @@ -1,6 +1,6 @@ use chrono::Duration; use dotenv::dotenv; -use nash_native_client::ws_client::client::Environment; +use nash_native_client::Environment; use openlimits::{ exchange::{ExchangeAccount, OpenLimits}, model::OpenMarketOrderRequest, diff --git a/tests/nash/market.rs b/tests/nash/market.rs index 86a0bfd6..19a5a86a 100644 --- a/tests/nash/market.rs +++ b/tests/nash/market.rs @@ -1,4 +1,4 @@ -use nash_native_client::ws_client::client::Environment; +use nash_native_client::Environment; use openlimits::{ exchange::{ExchangeMarketData, OpenLimits}, exchange_info::ExchangeInfoRetrieval, diff --git a/tests/nash/websocket.rs b/tests/nash/websocket.rs index 9ddc59c9..ba445852 100644 --- a/tests/nash/websocket.rs +++ b/tests/nash/websocket.rs @@ -1,8 +1,10 @@ use dotenv::dotenv; -use nash_native_client::ws_client::client::Environment; +use nash_native_client::Environment; use openlimits::{exchange_ws::OpenLimitsWs, model::websocket::Subscription, nash::NashWebsocket}; use std::{env, sync::mpsc::sync_channel}; use tokio::time::Duration; +use openlimits::nash::{NashParameters, NashCredentials}; +use openlimits::exchange_ws::ExchangeWs; async fn test_subscription_callback(websocket: OpenLimitsWs, sub: Subscription) { let (tx, rx) = sync_channel(0); @@ -18,14 +20,14 @@ async fn test_subscription_callback(websocket: OpenLimitsWs, sub: rx.recv().expect("Couldn't receive sync message."); } -#[tokio::test(core_threads = 2)] +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn orderbook() { let client = init().await; let sub = Subscription::OrderBookUpdates("btc_usdc".to_string()); test_subscription_callback(client, sub).await; } -#[tokio::test(core_threads = 2)] +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn trades() { let client = init().await; let sub = Subscription::Trades("btc_usdc".to_string()); @@ -35,14 +37,17 @@ async fn trades() { async fn init() -> OpenLimitsWs { dotenv().ok(); - let websocket = NashWebsocket::with_credential( - &env::var("NASH_API_SECRET").expect("Couldn't get environment variable."), - &env::var("NASH_API_KEY").expect("Couldn't get environment variable."), - 1234, - Environment::Sandbox, - Duration::new(10, 0), - None, - ) + let websocket = NashWebsocket::new(NashParameters { + credentials: Some(NashCredentials { + secret: env::var("NASH_API_SECRET").expect("Couldn't get environment variable."), + session: env::var("NASH_API_KEY").expect("Couldn't get environment variable."), + }), + affiliate_code: None, + client_id: 1234, + environment: Environment::Sandbox, + timeout: Duration::from_secs(10), + sign_states_loop_interval: None, + }) .await .expect("Couldn't connect.");