Files
foxhunt/crates/ctrader-openapi/src/market_data.rs
jgrusewski 9c3d741a08 refactor: restructure repo — crates/, bin/, testing/ layout
Move 17 library crates into crates/, CLI binary into bin/fxt,
consolidate 10 test crates into testing/, split config crate
from deployment config files.

Root directory reduced from 38+ to ~17 directories.
All Cargo.toml paths and build.rs proto refs updated.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 11:56:00 +01:00

82 lines
2.5 KiB
Rust

//! 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(())
}