use super::{
AccountId, ContractId, Hub, RealtimeError, RealtimeGeneration, RealtimeInner, Value, Weak,
};
#[derive(Clone)]
pub struct RealtimeSession {
pub(super) inner: Weak<RealtimeInner>,
pub(super) generation: RealtimeGeneration,
}
impl RealtimeSession {
#[must_use]
pub const fn generation(&self) -> RealtimeGeneration {
self.generation
}
pub async fn invoke(
&self,
target: impl Into<String>,
arguments: Vec<Value>,
) -> Result<(), RealtimeError> {
self.send_invocation(target.into(), arguments).await
}
pub async fn subscribe_contract_trades(
&self,
contract: &ContractId,
) -> Result<(), RealtimeError> {
self.ensure_hub(Hub::Market)?;
self.contract_invocation("SubscribeContractTrades", contract)
.await
}
pub async fn unsubscribe_contract_trades(
&self,
contract: &ContractId,
) -> Result<(), RealtimeError> {
self.ensure_hub(Hub::Market)?;
self.contract_invocation("UnsubscribeContractTrades", contract)
.await
}
pub async fn subscribe_contract_quotes(
&self,
contract: &ContractId,
) -> Result<(), RealtimeError> {
self.ensure_hub(Hub::Market)?;
self.contract_invocation("SubscribeContractQuotes", contract)
.await
}
pub async fn unsubscribe_contract_quotes(
&self,
contract: &ContractId,
) -> Result<(), RealtimeError> {
self.ensure_hub(Hub::Market)?;
self.contract_invocation("UnsubscribeContractQuotes", contract)
.await
}
pub async fn subscribe_contract_depth(
&self,
contract: &ContractId,
) -> Result<(), RealtimeError> {
self.ensure_hub(Hub::Market)?;
self.contract_invocation("SubscribeContractMarketDepth", contract)
.await
}
pub async fn unsubscribe_contract_depth(
&self,
contract: &ContractId,
) -> Result<(), RealtimeError> {
self.ensure_hub(Hub::Market)?;
self.contract_invocation("UnsubscribeContractMarketDepth", contract)
.await
}
pub async fn subscribe_accounts(&self) -> Result<(), RealtimeError> {
self.ensure_hub(Hub::User)?;
self.send_invocation("SubscribeAccounts".to_owned(), Vec::new())
.await
}
pub async fn unsubscribe_accounts(&self) -> Result<(), RealtimeError> {
self.ensure_hub(Hub::User)?;
self.send_invocation("UnsubscribeAccounts".to_owned(), Vec::new())
.await
}
pub async fn subscribe_orders(&self, account: AccountId) -> Result<(), RealtimeError> {
self.ensure_hub(Hub::User)?;
self.account_invocation("SubscribeOrders", account).await
}
pub async fn unsubscribe_orders(&self, account: AccountId) -> Result<(), RealtimeError> {
self.ensure_hub(Hub::User)?;
self.account_invocation("UnsubscribeOrders", account).await
}
pub async fn subscribe_positions(&self, account: AccountId) -> Result<(), RealtimeError> {
self.ensure_hub(Hub::User)?;
self.account_invocation("SubscribePositions", account).await
}
pub async fn unsubscribe_positions(&self, account: AccountId) -> Result<(), RealtimeError> {
self.ensure_hub(Hub::User)?;
self.account_invocation("UnsubscribePositions", account)
.await
}
pub async fn subscribe_trades(&self, account: AccountId) -> Result<(), RealtimeError> {
self.ensure_hub(Hub::User)?;
self.account_invocation("SubscribeTrades", account).await
}
pub async fn unsubscribe_trades(&self, account: AccountId) -> Result<(), RealtimeError> {
self.ensure_hub(Hub::User)?;
self.account_invocation("UnsubscribeTrades", account).await
}
fn ensure_hub(&self, expected: Hub) -> Result<(), RealtimeError> {
if self.inner.upgrade().ok_or(RealtimeError::NotConnected)?.hub == expected {
Ok(())
} else {
Err(RealtimeError::WrongHub)
}
}
async fn contract_invocation(
&self,
target: &str,
contract: &ContractId,
) -> Result<(), RealtimeError> {
self.inner
.upgrade()
.ok_or(RealtimeError::NotConnected)?
.send_invocation(
Some(self.generation),
target.to_owned(),
vec![Value::String(contract.to_string())],
)
.await
}
async fn account_invocation(
&self,
target: &str,
account: AccountId,
) -> Result<(), RealtimeError> {
self.inner
.upgrade()
.ok_or(RealtimeError::NotConnected)?
.send_invocation(
Some(self.generation),
target.to_owned(),
vec![Value::from(account.get())],
)
.await
}
async fn send_invocation(
&self,
target: String,
arguments: Vec<Value>,
) -> Result<(), RealtimeError> {
self.inner
.upgrade()
.ok_or(RealtimeError::NotConnected)?
.send_invocation(Some(self.generation), target, arguments)
.await
}
}
impl std::fmt::Debug for RealtimeSession {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("RealtimeSession")
.field("generation", &self.generation)
.finish_non_exhaustive()
}
}