Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion BinaryOptionsToolsV2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ mod validator;

// use config::PyConfig;
use logs::{LogBuilder, Logger, StreamLogsIterator, StreamLogsLayer, start_tracing};
use pocketoption::{RawPocketOption, RawStreamIterator, StreamIterator};
use pocketoption::{RawPocketOption, RawStreamIterator, StreamIterator, RawHandle, RawHandler};
use pyo3::prelude::*;
use validator::RawValidator;

Expand Down
120 changes: 120 additions & 0 deletions BinaryOptionsToolsV2/src/pocketoption.rs
Original file line number Diff line number Diff line change
Expand Up @@ -780,3 +780,123 @@ impl RawStreamIterator {
})
}
}

#[pymethods]
impl RawHandle {
/// Create a new RawHandler bound to the given validator
pub fn create<'py>(
&self,
py: Python<'py>,
validator: Bound<'py, RawValidator>,
keep_alive_message: Option<String>,
) -> PyResult<Bound<'py, PyAny>> {
let handle = self.handle.clone();
let validator = validator.get().clone();
future_into_py(py, async move {
let crate_validator: CrateValidator = validator.into();
let keep_alive = keep_alive_message.map(|msg| {
binary_options_tools::pocketoption::modules::raw::Outgoing::Text(msg)
});
let handler = handle
.create(crate_validator, keep_alive)
.await
.map_err(BinaryErrorPy::from)?;
Python::with_gil(|py| RawHandler { handler: Arc::new(Mutex::new(handler)) }.into_py_any(py))
})
}

/// Remove an existing handler by ID
pub fn remove<'py>(&self, py: Python<'py>, id: String) -> PyResult<Bound<'py, PyAny>> {
let handle = self.handle.clone();
future_into_py(py, async move {
let uuid = Uuid::parse_str(&id).map_err(BinaryErrorPy::from)?;
let existed = handle.remove(uuid).await.map_err(BinaryErrorPy::from)?;
Ok(existed)
})
}
}

#[pymethods]
impl RawHandler {
/// Get the handler's ID
pub fn id(&self) -> String {
let handler = self.handler.blocking_lock();
handler.id().to_string()
}

/// Send a text message
pub fn send_text<'py>(
&self,
py: Python<'py>,
text: String,
) -> PyResult<Bound<'py, PyAny>> {
let handler = self.handler.clone();
future_into_py(py, async move {
let handler = handler.lock().await;
handler.send_text(text).await.map_err(BinaryErrorPy::from)?;
Ok(())
})
}

/// Send a binary message
pub fn send_binary<'py>(
&self,
py: Python<'py>,
data: Vec<u8>,
) -> PyResult<Bound<'py, PyAny>> {
let handler = self.handler.clone();
future_into_py(py, async move {
let handler = handler.lock().await;
handler.send_binary(data).await.map_err(BinaryErrorPy::from)?;
Ok(())
})
}

/// Send a message and wait for the next matching response
pub fn send_and_wait<'py>(
&self,
py: Python<'py>,
message: String,
) -> PyResult<Bound<'py, PyAny>> {
let handler = self.handler.clone();
future_into_py(py, async move {
let handler = handler.lock().await;
let msg = binary_options_tools::pocketoption::modules::raw::Outgoing::Text(message);
let response = handler
.send_and_wait(msg)
.await
.map_err(BinaryErrorPy::from)?;
Ok(arc_message_to_string(&response))
})
}

/// Wait for the next message that matches this handler's validator
pub fn wait_next<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
let handler = self.handler.clone();
future_into_py(py, async move {
let handler = handler.lock().await;
let response = handler.wait_next().await.map_err(BinaryErrorPy::from)?;
Ok(arc_message_to_string(&response))
})
}

/// Subscribe to messages matching this handler's validator
/// Returns an iterator that yields matching messages
pub fn subscribe<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
let handler = self.handler.blocking_lock();
let receiver = handler.subscribe();

// Create a boxed stream that yields String values
let boxed_stream = async_stream::stream! {
while let Ok(msg) = receiver.recv().await {
let msg_str = arc_message_to_string(&msg);
yield Ok(msg_str);
}
}
.boxed()
.fuse();

let stream = Arc::new(Mutex::new(boxed_stream));
RawStreamIterator { stream }.into_bound_py_any(py)
}
}
9 changes: 5 additions & 4 deletions crates/binary_options_tools/src/pocketoption/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,11 +346,12 @@ impl Asset {
&self.allowed_candles
}

/// Validates if the asset can be used for trading at the given time
/// It checks, if the time is in the allowed candle durations
/// and also if the asset is active.
/// Validates if the asset can be used for trading
/// It checks if the asset is active.
/// The error thrown allows users to understand why the asset is not valid for trading.
pub fn validate(&self, time: u32) -> PocketResult<()> {
///
/// Note: Time validation has been removed to allow trading at any expiration time.
pub fn validate(&self, _time: u32) -> PocketResult<()> {
if !self.is_active {
return Err(PocketError::InvalidAsset("Asset is not active".into()));
}
Expand Down