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>
82 lines
2.5 KiB
Rust
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(())
|
|
}
|