//! Market data subscription helpers for the cTrader Open API. //! //! Provides functions to subscribe/unsubscribe to spot price events. use prost::Message; use tracing::info; use crate::dispatch::MessageDispatcher; use crate::error::{CTraderError, Result}; use crate::proto::{self, ProtoMessage}; /// Subscribe to spot price events for the given symbol IDs. pub async fn subscribe_spots( dispatcher: &MessageDispatcher, account_id: i64, symbol_ids: &[i64], timeout: std::time::Duration, ) -> Result<()> { info!(symbols = ?symbol_ids, "subscribing to spot events"); let req = proto::ProtoOaSubscribeSpotsReq { payload_type: Some(proto::PT_SUBSCRIBE_SPOTS_REQ as i32), ctid_trader_account_id: account_id, symbol_id: symbol_ids.to_vec(), subscribe_to_spot_timestamp: Some(true), }; let envelope = ProtoMessage { payload_type: proto::PT_SUBSCRIBE_SPOTS_REQ, payload: Some(req.encode_to_vec()), client_msg_id: None, }; let resp = dispatcher.send_request(envelope, timeout).await?; if resp.payload_type != proto::PT_SUBSCRIBE_SPOTS_RES { return Err(CTraderError::ProtocolError(format!( "expected SubscribeSpotsRes ({}), got {}", proto::PT_SUBSCRIBE_SPOTS_RES, resp.payload_type ))); } info!(count = symbol_ids.len(), "spot subscription confirmed"); Ok(()) } /// Unsubscribe from spot price events for the given symbol IDs. pub async fn unsubscribe_spots( dispatcher: &MessageDispatcher, account_id: i64, symbol_ids: &[i64], timeout: std::time::Duration, ) -> Result<()> { info!(symbols = ?symbol_ids, "unsubscribing from spot events"); let req = proto::ProtoOaUnsubscribeSpotsReq { payload_type: Some(proto::PT_UNSUBSCRIBE_SPOTS_REQ as i32), ctid_trader_account_id: account_id, symbol_id: symbol_ids.to_vec(), }; let envelope = ProtoMessage { payload_type: proto::PT_UNSUBSCRIBE_SPOTS_REQ, payload: Some(req.encode_to_vec()), client_msg_id: None, }; let resp = dispatcher.send_request(envelope, timeout).await?; if resp.payload_type != proto::PT_UNSUBSCRIBE_SPOTS_RES { return Err(CTraderError::ProtocolError(format!( "expected UnsubscribeSpotsRes ({}), got {}", proto::PT_UNSUBSCRIBE_SPOTS_RES, resp.payload_type ))); } info!(count = symbol_ids.len(), "spot unsubscription confirmed"); Ok(()) }