Skip to main content

Raw Module Architecture and Usage

This document explains the design of the Raw module: a flexible, validator-driven pipeline that lets you build features not covered by the built-in API (e.g., custom signals) while reusing the WebSocket connection, reconnection, and keep-alive logic.

Overview​

  • Platform (PocketOption client) β†’ Create handler for a specific validator β†’ Handler interacts with Raw module to send/receive.
  • You define a Validator that decides which incoming WS messages you care about.
  • The Raw module routes matching messages into a per-validator stream.
  • Handlers can send text/binary messages and optionally define a keep-alive message resent on reconnect.
  • Dropping a handler removes its validator and stream automatically.

Components​

  • Validator: enum + trait; runs on &str built from WS message content.
  • RawApiModule: ApiModule that maintains a map of validators and their streams.
  • RawHandle: top-level handle obtained from PocketOption to create/remove handlers.
  • RawHandler: per-validator handle to send/receive and subscribe to matching messages.

Message Flow​

flowchart LR
WS[(WebSocket)] --> Router
subgraph Client
Router -->|rule: RawRule| RawModule
RawModule -->|match by Validator| Streams
end
Streams --> UserCode
  • Router forwards only messages for which at least one registered validator returns true.
  • RawModule fans out each message to all matching validator streams.

Lifecycle​

sequenceDiagram
participant User as User Code
participant PO as PocketOption
participant RAW as RawApiModule
participant WS as WebSocket

User->>PO: raw_handle()
PO-->>User: RawHandle
User->>RAW: create(validator, keep_alive)
RAW->>RAW: register validator + stream
RAW-->>User: RawHandler (id, receiver)
User->>WS: send (via RawHandler)
WS-->>RAW: messages
RAW->>User: route to stream if validator matches
User--xRAW: drop RawHandler
RAW->>RAW: remove validator + stream

API Sketch​

PocketOption​

  • raw_handle() β†’ RawHandle
  • create_raw_handler(validator, keep_alive) β†’ RawHandler

RawHandle​

  • create(validator, keep_alive) β†’ RawHandler
  • remove(id) β†’ bool

RawHandler​

  • id() β†’ Uuid
  • send_text(text)
  • send_binary(bytes)
  • send_and_wait(msg) β†’ next matching Message
  • wait_next() β†’ next matching Message
  • subscribe() β†’ AsyncReceiver<Message>
  • Drop: auto-remove validator and stream

Keep-Alive on Reconnect​

If a handler is created with a keep_alive message, the module will re-send it after reconnects so servers maintain your subscription.

Notes​

  • Validators are stored by UUID; you can remove them explicitly or by dropping their handler.
  • Incoming messages are transformed to String for validation; original Message (text/binary) is delivered to the stream.
  • The module is best-effort for fan-out; if a user stream is closed, the send is ignored.

Example (Rust)​

use binary_options_tools_pocketoption::{PocketOption};
use binary_options_tools_pocketoption::validator::Validator;
use binary_options_tools_pocketoption::pocketoption::modules::raw::Outgoing;

async fn demo(ssid: &str) -> anyhow::Result<()> {
let api = PocketOption::new(ssid).await?;
let validator = Validator::contains("updateStream".to_string());
let handler = api
.create_raw_handler(validator, Some(Outgoing::Text("42[\"ping\"]".into())))
.await?;

handler.send_text("42[\"hello\"]").await?;
let msg = handler.wait_next().await?; // next matching Message
println!("got: {:?}", msg);
Ok(())
}

Example (Python)​

import asyncio
import json
from BinaryOptionsToolsV2 import PocketOptionAsync, Validator

async def main(ssid: str):
async with PocketOptionAsync(ssid) as api:
# Create validator for balance messages
validator = Validator.contains('"balance"')

# Create raw handler
handler = await api.create_raw_handler(validator)

# Send custom message
await handler.send_text('42["getBalance"]')

# Wait for response
response = await handler.wait_next()
data = json.loads(response)
print(f"Balance: {data.get('balance', 'N/A')}")

asyncio.run(main("your-ssid"))

Validator Types​

Basic Validators​

  • starts_with(prefix) - Check if message starts with prefix
  • ends_with(suffix) - Check if message ends with suffix
  • contains(substring) - Check if message contains substring
  • regex(pattern) - Match against regex pattern

Logical Combinators​

  • ne(validator) - Negate a validator (NOT)
  • all(validators) - All validators must match (AND)
  • any(validators) - At least one validator must match (OR)

Instance Method​

  • check(message) - Test if message matches validator

Use Cases​

1. Custom Message Monitoring​

validator = Validator.all([
Validator.starts_with("42["),
Validator.contains('"type":"candle"')
])
handler = await client.create_raw_handler(validator, None)

2. Low-Level Protocol Implementation​

async def send_custom_command(handler, command, args):
message = json.dumps([command, args])
response = await handler.send_and_wait(message)
return json.loads(response)

3. Debugging and Logging​

error_validator = Validator.contains("error")
error_handler = await client.create_raw_handler(error_validator, None)

while True:
error_msg = await error_handler.wait_next()
print(f"ERROR: {error_msg}")

4. Multiple Subscriptions​

balance_handler = await client.create_raw_handler(
Validator.contains("balance"), None
)
trade_handler = await client.create_raw_handler(
Validator.contains("trade"), None
)

Architecture​

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ BinaryOptionsToolsUni β”‚
β”‚ β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ Validator β”‚ β”‚ RawHandler β”‚ β”‚
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚
β”‚ β”‚ β€’ starts_withβ”‚ β”‚ β€’ send_text β”‚ β”‚
β”‚ β”‚ β€’ contains β”‚ β”‚ β€’ send_binary β”‚ β”‚
β”‚ β”‚ β€’ regex β”‚ β”‚ β€’ wait_next β”‚ β”‚
β”‚ β”‚ β€’ all/any/ne β”‚ β”‚ β€’ send_and_waitβ”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”‚ β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”‚ β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ PocketOption Client β”‚ β”‚
β”‚ β”‚ β”‚ β”‚
β”‚ β”‚ β€’ create_raw_handler() β”‚ β”‚
β”‚ β”‚ β€’ payout() β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ binary_options_tools β”‚
β”‚ (Rust Core Library) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜