diff --git a/src/bin/ws_bbo.rs b/src/bin/ws_bbo.rs new file mode 100644 index 00000000..f62b4941 --- /dev/null +++ b/src/bin/ws_bbo.rs @@ -0,0 +1,30 @@ +use hyperliquid_rust_sdk::{BaseUrl, InfoClient, Message, Subscription}; +use log::info; +use tokio::{ + spawn, + sync::mpsc::unbounded_channel, + time::{sleep, Duration}, +}; + +#[tokio::main] +async fn main() { + env_logger::init(); + let mut info_client = InfoClient::new(None, Some(BaseUrl::Testnet)).await.unwrap(); + let coin = "BTC".to_string(); + + let (sender, mut receiver) = unbounded_channel(); + let subscription_id = info_client + .subscribe(Subscription::Bbo { coin }, sender) + .await + .unwrap(); + + spawn(async move { + sleep(Duration::from_secs(30)).await; + info!("Unsubscribing from bbo"); + info_client.unsubscribe(subscription_id).await.unwrap() + }); + + while let Some(Message::Bbo(bbo)) = receiver.recv().await { + info!("Received bbo: {bbo:?}"); + } +} diff --git a/src/ws/message_types.rs b/src/ws/message_types.rs index 4af5926b..9036b7ff 100644 --- a/src/ws/message_types.rs +++ b/src/ws/message_types.rs @@ -60,3 +60,8 @@ pub struct WebData2 { pub struct ActiveAssetCtx { pub data: ActiveAssetCtxData, } + +#[derive(Deserialize, Clone, Debug)] +pub struct Bbo { + pub data: BboData, +} diff --git a/src/ws/sub_structs.rs b/src/ws/sub_structs.rs index d72d7100..0028477d 100644 --- a/src/ws/sub_structs.rs +++ b/src/ws/sub_structs.rs @@ -322,3 +322,11 @@ pub struct SpotAssetCtx { pub shared: SharedAssetCtx, pub circulating_supply: String, } + +#[derive(Deserialize, Clone, Debug)] +#[serde(rename_all = "camelCase")] +pub struct BboData { + pub coin: String, + pub time: u64, + pub bbo: Vec>, +} diff --git a/src/ws/ws_manager.rs b/src/ws/ws_manager.rs index 6ee94e39..14a2e2c9 100755 --- a/src/ws/ws_manager.rs +++ b/src/ws/ws_manager.rs @@ -1,6 +1,6 @@ use crate::{ prelude::*, - ws::message_types::{AllMids, Candle, L2Book, OrderUpdates, Trades, User}, + ws::message_types::{AllMids, Bbo, Candle, L2Book, OrderUpdates, Trades, User}, ActiveAssetCtx, Error, Notification, UserFills, UserFundings, UserNonFundingLedgerUpdates, WebData2, }; @@ -62,6 +62,7 @@ pub enum Subscription { UserFundings { user: H160 }, UserNonFundingLedgerUpdates { user: H160 }, ActiveAssetCtx { coin: String }, + Bbo { coin: String }, } #[derive(Deserialize, Clone, Debug)] @@ -83,6 +84,7 @@ pub enum Message { Notification(Notification), WebData2(WebData2), ActiveAssetCtx(ActiveAssetCtx), + Bbo(Bbo), Pong, } @@ -267,6 +269,10 @@ impl WsManager { }) .map_err(|e| Error::JsonParse(e.to_string())) } + Message::Bbo(bbo) => serde_json::to_string(&Subscription::Bbo { + coin: bbo.data.coin.clone(), + }) + .map_err(|e| Error::JsonParse(e.to_string())), Message::SubscriptionResponse | Message::Pong => Ok(String::default()), Message::NoData => Ok("".to_string()), Message::HyperliquidError(err) => Ok(format!("hyperliquid error: {err:?}")),