mirror of
https://github.com/floor-licker/polyfill-rs.git
synced 2026-08-25 10:28:07 +00:00
fix: fix to wss subscription sigs
This commit is contained in:
@@ -149,7 +149,7 @@ use polyfill_rs::{OrderBookImpl, WebSocketStream};
|
|||||||
|
|
||||||
// Real-time order book with fixed-point optimizations
|
// Real-time order book with fixed-point optimizations
|
||||||
let mut book = OrderBookImpl::new("token_id".to_string(), 100);
|
let mut book = OrderBookImpl::new("token_id".to_string(), 100);
|
||||||
let mut stream = WebSocketStream::new("wss://ws-subscriptions-clob.polymarket.com").await?;
|
let mut stream = WebSocketStream::new("wss://ws-subscriptions-clob.polymarket.com/ws/market").await?;
|
||||||
|
|
||||||
// Process thousands of updates per second
|
// Process thousands of updates per second
|
||||||
while let Some(update) = stream.next().await {
|
while let Some(update) = stream.next().await {
|
||||||
@@ -386,7 +386,7 @@ Here's how you connect to live market data. The library handles all the annoying
|
|||||||
```rust
|
```rust
|
||||||
use polyfill_rs::{WebSocketStream, StreamManager};
|
use polyfill_rs::{WebSocketStream, StreamManager};
|
||||||
|
|
||||||
let mut stream = WebSocketStream::new("wss://clob.polymarket.com/ws");
|
let mut stream = WebSocketStream::new("wss://ws-subscriptions-clob.polymarket.com/ws/market");
|
||||||
|
|
||||||
// Set up authentication (you'll need API credentials)
|
// Set up authentication (you'll need API credentials)
|
||||||
let auth = WssAuth {
|
let auth = WssAuth {
|
||||||
@@ -505,7 +505,7 @@ let reconnect_config = ReconnectConfig {
|
|||||||
backoff_multiplier: 2.0, // Double delay each time
|
backoff_multiplier: 2.0, // Double delay each time
|
||||||
};
|
};
|
||||||
|
|
||||||
let stream = WebSocketStream::new("wss://clob.polymarket.com/ws")
|
let stream = WebSocketStream::new("wss://ws-subscriptions-clob.polymarket.com/ws/market")
|
||||||
.with_reconnect_config(reconnect_config);
|
.with_reconnect_config(reconnect_config);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -579,7 +579,7 @@ impl PolyfillDemo {
|
|||||||
info!("=== Demo 8: Streaming Capabilities ===");
|
info!("=== Demo 8: Streaming Capabilities ===");
|
||||||
|
|
||||||
// Create a mock WebSocket stream
|
// Create a mock WebSocket stream
|
||||||
let _stream = WebSocketStream::new("wss://stream.polymarket.com");
|
let _stream = WebSocketStream::new("wss://ws-subscriptions-clob.polymarket.com/ws/market");
|
||||||
|
|
||||||
info!("Created WebSocket stream");
|
info!("Created WebSocket stream");
|
||||||
|
|
||||||
|
|||||||
+65
-41
@@ -160,12 +160,10 @@ impl WebSocketStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Send subscription message in the format expected by Polymarket
|
// Send subscription message in the format expected by Polymarket
|
||||||
let message = serde_json::json!({
|
// The subscription struct will serialize correctly with proper field names
|
||||||
"auth": subscription.auth,
|
let message = serde_json::to_value(&subscription).map_err(|e| {
|
||||||
"markets": subscription.markets,
|
PolyfillError::parse(format!("Failed to serialize subscription: {}", e), None)
|
||||||
"asset_ids": subscription.asset_ids,
|
})?;
|
||||||
"type": subscription.channel_type,
|
|
||||||
});
|
|
||||||
|
|
||||||
self.send_message(message).await?;
|
self.send_message(message).await?;
|
||||||
self.subscriptions.push(subscription.clone());
|
self.subscriptions.push(subscription.clone());
|
||||||
@@ -183,17 +181,67 @@ impl WebSocketStream {
|
|||||||
.clone();
|
.clone();
|
||||||
|
|
||||||
let subscription = WssSubscription {
|
let subscription = WssSubscription {
|
||||||
auth,
|
channel_type: "user".to_string(),
|
||||||
markets: Some(markets),
|
operation: Some("subscribe".to_string()),
|
||||||
asset_ids: None,
|
markets,
|
||||||
channel_type: "USER".to_string(),
|
asset_ids: Vec::new(),
|
||||||
|
initial_dump: Some(true),
|
||||||
|
custom_feature_enabled: None,
|
||||||
|
auth: Some(auth),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.subscribe_async(subscription).await
|
self.subscribe_async(subscription).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Subscribe to market channel (order book and trades)
|
/// Subscribe to market channel (order book and trades)
|
||||||
|
/// Market subscriptions do not require authentication
|
||||||
pub async fn subscribe_market_channel(&mut self, asset_ids: Vec<String>) -> Result<()> {
|
pub async fn subscribe_market_channel(&mut self, asset_ids: Vec<String>) -> Result<()> {
|
||||||
|
let subscription = WssSubscription {
|
||||||
|
channel_type: "market".to_string(),
|
||||||
|
operation: Some("subscribe".to_string()),
|
||||||
|
markets: Vec::new(),
|
||||||
|
asset_ids,
|
||||||
|
initial_dump: Some(true),
|
||||||
|
custom_feature_enabled: None,
|
||||||
|
auth: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.subscribe_async(subscription).await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Subscribe to market channel with custom features enabled
|
||||||
|
/// Custom features include: best_bid_ask, new_market, market_resolved events
|
||||||
|
pub async fn subscribe_market_channel_with_features(&mut self, asset_ids: Vec<String>) -> Result<()> {
|
||||||
|
let subscription = WssSubscription {
|
||||||
|
channel_type: "market".to_string(),
|
||||||
|
operation: Some("subscribe".to_string()),
|
||||||
|
markets: Vec::new(),
|
||||||
|
asset_ids,
|
||||||
|
initial_dump: Some(true),
|
||||||
|
custom_feature_enabled: Some(true),
|
||||||
|
auth: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.subscribe_async(subscription).await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Unsubscribe from market channel
|
||||||
|
pub async fn unsubscribe_market_channel(&mut self, asset_ids: Vec<String>) -> Result<()> {
|
||||||
|
let subscription = WssSubscription {
|
||||||
|
channel_type: "market".to_string(),
|
||||||
|
operation: Some("unsubscribe".to_string()),
|
||||||
|
markets: Vec::new(),
|
||||||
|
asset_ids,
|
||||||
|
initial_dump: None,
|
||||||
|
custom_feature_enabled: None,
|
||||||
|
auth: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.subscribe_async(subscription).await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Unsubscribe from user channel
|
||||||
|
pub async fn unsubscribe_user_channel(&mut self, markets: Vec<String>) -> Result<()> {
|
||||||
let auth = self
|
let auth = self
|
||||||
.auth
|
.auth
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@@ -201,42 +249,18 @@ impl WebSocketStream {
|
|||||||
.clone();
|
.clone();
|
||||||
|
|
||||||
let subscription = WssSubscription {
|
let subscription = WssSubscription {
|
||||||
auth,
|
channel_type: "user".to_string(),
|
||||||
markets: None,
|
operation: Some("unsubscribe".to_string()),
|
||||||
asset_ids: Some(asset_ids),
|
markets,
|
||||||
channel_type: "MARKET".to_string(),
|
asset_ids: Vec::new(),
|
||||||
|
initial_dump: None,
|
||||||
|
custom_feature_enabled: None,
|
||||||
|
auth: Some(auth),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.subscribe_async(subscription).await
|
self.subscribe_async(subscription).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unsubscribe from market data
|
|
||||||
pub async fn unsubscribe_async(&mut self, token_ids: &[String]) -> Result<()> {
|
|
||||||
// Note: Polymarket WebSocket API doesn't seem to have explicit unsubscribe
|
|
||||||
// We'll just remove from our local subscriptions
|
|
||||||
self.subscriptions
|
|
||||||
.retain(|sub| match sub.channel_type.as_str() {
|
|
||||||
"USER" => {
|
|
||||||
if let Some(markets) = &sub.markets {
|
|
||||||
!token_ids.iter().any(|id| markets.contains(id))
|
|
||||||
} else {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"MARKET" => {
|
|
||||||
if let Some(asset_ids) = &sub.asset_ids {
|
|
||||||
!token_ids.iter().any(|id| asset_ids.contains(id))
|
|
||||||
} else {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => true,
|
|
||||||
});
|
|
||||||
|
|
||||||
info!("Unsubscribed from {} tokens", token_ids.len());
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Handle incoming WebSocket messages
|
/// Handle incoming WebSocket messages
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
async fn handle_message(
|
async fn handle_message(
|
||||||
|
|||||||
+20
-7
@@ -675,15 +675,28 @@ pub struct WssAuth {
|
|||||||
/// WebSocket subscription request
|
/// WebSocket subscription request
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct WssSubscription {
|
pub struct WssSubscription {
|
||||||
/// Authentication information
|
/// Channel type: "market" or "user"
|
||||||
pub auth: WssAuth,
|
|
||||||
/// Array of markets (condition IDs) for USER channel
|
|
||||||
pub markets: Option<Vec<String>>,
|
|
||||||
/// Array of asset IDs (token IDs) for MARKET channel
|
|
||||||
pub asset_ids: Option<Vec<String>>,
|
|
||||||
/// Channel type: "USER" or "MARKET"
|
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
pub channel_type: String,
|
pub channel_type: String,
|
||||||
|
/// Operation type: "subscribe" or "unsubscribe"
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub operation: Option<String>,
|
||||||
|
/// Array of markets (condition IDs) for USER channel
|
||||||
|
#[serde(default)]
|
||||||
|
pub markets: Vec<String>,
|
||||||
|
/// Array of asset IDs (token IDs) for MARKET channel
|
||||||
|
/// Note: Field name is "assets_ids" (with 's') per Polymarket API spec
|
||||||
|
#[serde(rename = "assets_ids", default)]
|
||||||
|
pub asset_ids: Vec<String>,
|
||||||
|
/// Request initial state dump
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub initial_dump: Option<bool>,
|
||||||
|
/// Enable custom features (best_bid_ask, new_market, market_resolved)
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub custom_feature_enabled: Option<bool>,
|
||||||
|
/// Authentication information (only for USER channel)
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub auth: Option<WssAuth>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// WebSocket message types for streaming
|
/// WebSocket message types for streaming
|
||||||
|
|||||||
Reference in New Issue
Block a user