Skip to content

Commit 95dc9ad

Browse files
authored
Merge pull request #16 from pawsengineer/develop
bump version to 0.1.5
2 parents 7238b9d + b96d452 commit 95dc9ad

10 files changed

Lines changed: 234 additions & 64 deletions

File tree

‎Cargo.lock‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Cargo.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "polymarket-rs"
3-
version = "0.1.4"
3+
version = "0.1.5"
44
edition = "2021"
55
authors = ["Pawsengineer <play.pawsengineer@gmail.com>"]
66
description = "Rust client library for the Polymarket CLOB and Data API"

‎examples/authenticated_trading.rs‎

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use alloy_signer_local::PrivateKeySigner;
22
use polymarket_rs::client::{AuthenticatedClient, TradingClient};
33
use polymarket_rs::orders::OrderBuilder;
44
use polymarket_rs::types::{CreateOrderOptions, OrderArgs, Side, SignatureType};
5-
use polymarket_rs::Result;
5+
use polymarket_rs::{OrderType, Result};
66
use rust_decimal::Decimal;
77
use std::str::FromStr;
88

@@ -66,46 +66,43 @@ async fn main() -> Result<()> {
6666
Side::Buy,
6767
);
6868

69-
let _options = CreateOrderOptions::default()
69+
let options = CreateOrderOptions::default()
7070
.tick_size(Decimal::from_str("0.01").unwrap())
7171
.neg_risk(false);
7272

73-
// Note: This creates the order but doesn't post it
74-
// Uncomment the following to actually post:
75-
// let signed_order = trading_client.create_order(
76-
// &_order_args,
77-
// None, // expiration (defaults to 0 = no expiration)
78-
// None, // extras (defaults to ExtraOrderArgs::default())
79-
// _options,
80-
// )?;
81-
//
82-
// println!("Created signed order with salt: {}", signed_order.salt);
83-
//
84-
// // Post the order
85-
// let result = trading_client.post_order(signed_order, OrderType::Gtc).await?;
86-
// println!("Order posted: {:?}", result);
73+
let signed_order = trading_client.create_order(
74+
&_order_args,
75+
None, // expiration (defaults to 0 = no expiration)
76+
None, // extras (defaults to ExtraOrderArgs::default())
77+
options,
78+
)?;
79+
80+
println!("Created signed order with salt: {}", signed_order.salt);
8781

88-
println!("Order creation example completed (not posted)");
82+
// Post the order
83+
let result = trading_client
84+
.post_order(signed_order, OrderType::Gtc)
85+
.await?;
86+
println!("Order posted: {:?}", result);
8987

9088
// Step 5: Cancel market orders (example - NOT executed)
9189
println!("\n5. Cancel market orders example...");
92-
// Uncomment to cancel orders for a specific market:
93-
// let result = trading_client.cancel_market_orders(Some("0xaaa"), None).await?;
90+
91+
// Cancel orders for a specific market:
92+
let result = trading_client
93+
.cancel_market_orders(Some("0xaaa"), None)
94+
.await?;
9495
// Or cancel by asset_id:
9596
// let result = trading_client.cancel_market_orders(None, Some("100")).await?;
9697
// Or both:
9798
// let result = trading_client.cancel_market_orders(Some("0xaaa"), Some("100")).await?;
98-
println!("Cancel market orders example completed (not executed)");
99+
println!("Cancelled orders: {:?}", result);
99100

100101
// Step 6: Get trade history
101102
println!("\n6. Fetching trade history...");
102103
let trades = trading_client.get_trades(Default::default()).await?;
103104
println!("Trade history: {:?}", trades);
104105

105-
println!("\n✓ Example completed successfully!");
106-
println!("\nNOTE: This example did not post any actual orders.");
107-
println!("Uncomment the posting code to execute real trades.");
108-
109106
// ========================================================================
110107
// POLYPROXY WALLET EXAMPLE
111108
// ========================================================================

‎examples/post_multiple_orders.rs‎

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
use alloy_signer_local::PrivateKeySigner;
2+
use polymarket_rs::client::{AuthenticatedClient, TradingClient};
3+
use polymarket_rs::orders::OrderBuilder;
4+
use polymarket_rs::types::{
5+
CreateOrderOptions, OrderArgs, OrderType, PostOrderArgs, Side, SignatureType,
6+
};
7+
use polymarket_rs::Result;
8+
use rust_decimal::Decimal;
9+
use std::str::FromStr;
10+
11+
#[tokio::main]
12+
async fn main() -> Result<()> {
13+
// Replace with your actual private key
14+
let private_key =
15+
std::env::var("PRIVATE_KEY").expect("PRIVATE_KEY environment variable not set");
16+
17+
let signer = PrivateKeySigner::from_str(&private_key).expect("Invalid private key");
18+
19+
let chain_id = 137; // Polygon Mainnet
20+
let host = "https://clob.polymarket.com";
21+
22+
println!("Signer address: {}", signer.address());
23+
24+
// Step 1: Create or derive API credentials
25+
println!("\n1. Creating/deriving API credentials...");
26+
let auth_client = AuthenticatedClient::new(host, signer.clone(), chain_id, None, None);
27+
let api_creds = auth_client.create_or_derive_api_key().await?;
28+
println!("API Key: {}", api_creds.api_key);
29+
println!("Successfully authenticated!");
30+
31+
// Step 2: Create a trading client
32+
println!("\n2. Setting up trading client...");
33+
let order_builder = OrderBuilder::new(signer.clone(), Some(SignatureType::Eoa), None);
34+
35+
let trading_client = TradingClient::new(
36+
host,
37+
signer.clone(),
38+
chain_id,
39+
api_creds.clone(),
40+
order_builder,
41+
);
42+
43+
// Step 3: Create multiple orders
44+
println!("\n3. Creating multiple orders...");
45+
46+
// Specific token IDs
47+
let token_id_1 = "";
48+
let token_id_2 = "";
49+
50+
// Create order options (adjust tick_size and neg_risk as needed)
51+
let options = CreateOrderOptions::default()
52+
.tick_size(Decimal::from_str("0.01").unwrap())
53+
.neg_risk(false);
54+
55+
// Create first order: BUY 10 tokens at 0.50
56+
let order_args_1 = OrderArgs::new(
57+
token_id_1,
58+
Decimal::from_str("0.50").unwrap(), // price
59+
Decimal::from_str("10.0").unwrap(), // size
60+
Side::Buy,
61+
);
62+
63+
let signed_order_1 = trading_client.create_order(&order_args_1, None, None, options.clone())?;
64+
println!("Created order 1: BUY 10 @ 0.50");
65+
66+
// Create second order: SELL 15 tokens at 0.75
67+
let order_args_2 = OrderArgs::new(
68+
token_id_2,
69+
Decimal::from_str("0.75").unwrap(), // price
70+
Decimal::from_str("15.0").unwrap(), // size
71+
Side::Sell,
72+
);
73+
74+
let signed_order_2 = trading_client.create_order(&order_args_2, None, None, options.clone())?;
75+
println!("Created order 2: SELL 15 @ 0.75");
76+
77+
// Create third order: BUY 5 tokens at 0.60
78+
let order_args_3 = OrderArgs::new(
79+
token_id_1,
80+
Decimal::from_str("0.60").unwrap(), // price
81+
Decimal::from_str("5.0").unwrap(), // size
82+
Side::Buy,
83+
);
84+
85+
let signed_order_3 = trading_client.create_order(&order_args_3, None, None, options)?;
86+
println!("Created order 3: BUY 5 @ 0.60");
87+
88+
// Step 4: Post all orders at once
89+
println!("\n4. Posting multiple orders...");
90+
91+
let results = trading_client
92+
.post_orders(&[
93+
PostOrderArgs::new(signed_order_1, OrderType::Gtc),
94+
PostOrderArgs::new(signed_order_2, OrderType::Gtc),
95+
PostOrderArgs::new(signed_order_3, OrderType::Gtc),
96+
])
97+
.await?;
98+
99+
println!("\n✅ Successfully posted {} orders!", results.len());
100+
101+
for (i, result) in results.iter().enumerate() {
102+
println!("\nOrder {}:", i + 1);
103+
println!(" Order ID: {}", result.order_id.as_str());
104+
println!(" Status: {}", result.status);
105+
println!(" Success: {}", result.success);
106+
if !result.error_msg.is_empty() {
107+
println!(" Error: {}", result.error_msg);
108+
}
109+
}
110+
Ok(())
111+
}

‎examples/websocket_market.rs‎

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use futures_util::StreamExt;
22
use polymarket_rs::types::WsEvent;
3-
use polymarket_rs::websocket::MarketWsClient;
3+
use polymarket_rs::websocket::{MarketWsClient, ReconnectConfig, ReconnectingStream};
4+
use std::time::Duration;
45

56
#[tokio::main]
67
async fn main() -> Result<(), Box<dyn std::error::Error>> {
@@ -12,13 +13,29 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
1213
"87769991026114894163580777793845523168226980076553814689875238288185044414090".to_string(),
1314
];
1415

15-
println!("Connecting to CLOB WebSocket...");
16+
println!("Connecting to CLOB WebSocket with auto-reconnect...");
1617
println!("Subscribing to {} token(s)", token_ids.len());
1718

18-
// Subscribe to market updates
19-
let (mut stream, _handle) = client.subscribe_with_handle(token_ids).await?;
19+
// Configure reconnection behavior
20+
let reconnect_config = ReconnectConfig {
21+
initial_delay: Duration::from_secs(1),
22+
max_delay: Duration::from_secs(30),
23+
multiplier: 2.0,
24+
max_attempts: None, // Infinite reconnection attempts
25+
};
26+
27+
// Create a reconnecting stream that will automatically reconnect on disconnection
28+
let mut stream = ReconnectingStream::new(reconnect_config, move || {
29+
let client = client.clone();
30+
let token_ids = token_ids.clone();
31+
async move {
32+
println!("🔄 Connecting to WebSocket...");
33+
let (stream, _handle) = client.subscribe_with_handle(token_ids).await?;
34+
println!("✅ Connected successfully!");
35+
Ok(stream)
36+
}
37+
});
2038

21-
println!("✅ Connected successfully!");
2239
println!("Waiting for events...\n");
2340

2441
// Process events as they arrive
@@ -79,8 +96,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
7996
}
8097
}
8198
Err(e) => {
82-
log::warn!("❌ Error: {}", e);
83-
break;
99+
// With ReconnectingStream, errors are logged but the stream continues
100+
// Only fatal errors (like max reconnection attempts) will terminate the stream
101+
eprintln!("⚠️ Error: {} - Reconnecting...", e);
84102
}
85103
}
86104
}

‎src/client/trading.rs‎

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::signing::EthSigner;
55
use crate::types::{
66
ApiCreds, CancelOrdersResponse, CreateOrderOptions, ExtraOrderArgs, MarketOrderArgs, OpenOrder,
77
OpenOrderParams, OpenOrdersResponse, OrderArgs, OrderBookSummary, OrderId, OrderType,
8-
PostOrder, PostOrderResponse, Side, SignedOrderRequest, TradeParams,
8+
PostOrder, PostOrderArgs, PostOrderResponse, Side, SignedOrderRequest, TradeParams,
99
};
1010

1111
/// Client for trading operations
@@ -122,6 +122,45 @@ impl TradingClient {
122122
.await
123123
}
124124

125+
/// Post multiple orders to the exchange
126+
///
127+
/// # Arguments
128+
/// * `orders` - Slice of order arguments with their types
129+
///
130+
/// # Example
131+
/// ```no_run
132+
/// # use polymarket_rs::client::TradingClient;
133+
/// # use polymarket_rs::types::{PostOrderArgs, OrderType};
134+
/// # async fn example(trading_client: &TradingClient, order1: polymarket_rs::types::SignedOrderRequest, order2: polymarket_rs::types::SignedOrderRequest) -> polymarket_rs::Result<()> {
135+
/// let results = trading_client.post_orders(&[
136+
/// PostOrderArgs::new(order1, OrderType::Gtc),
137+
/// PostOrderArgs::new(order2, OrderType::Gtc),
138+
/// ]).await?;
139+
/// # Ok(())
140+
/// # }
141+
/// ```
142+
pub async fn post_orders(&self, orders: &[PostOrderArgs]) -> Result<Vec<PostOrderResponse>> {
143+
let owner = self.api_creds.api_key.clone();
144+
145+
// Build array of PostOrder structs
146+
let post_orders: Vec<PostOrder> = orders
147+
.iter()
148+
.map(|arg| PostOrder::new(arg.order.clone(), owner.clone(), arg.order_type))
149+
.collect();
150+
151+
let headers = create_l2_headers(
152+
&self.signer,
153+
&self.api_creds,
154+
"POST",
155+
"/orders",
156+
Some(&post_orders),
157+
)?;
158+
159+
self.http_client
160+
.post("/orders", &post_orders, Some(headers))
161+
.await
162+
}
163+
125164
/// Create and post an order in one step
126165
///
127166
/// This is a convenience method that combines create_order and post_order.

‎src/lib.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ pub use alloy_signer_local::PrivateKeySigner;
3939
pub use error::{Error, Result};
4040
pub use types::{
4141
ApiCreds, AssetType, ConditionId, CreateOrderOptions, ExtraOrderArgs, MarketOrderArgs,
42-
OrderArgs, OrderId, OrderType, Side, SignatureType, TokenId,
42+
OrderArgs, OrderId, OrderType, PostOrderArgs, Side, SignatureType, TokenId,
4343
};
4444

4545
// Re-export clients

‎src/orders/price.rs‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::error::{Error, Result};
2-
use crate::types::OrderSummary;
2+
use crate::types::PriceLevel;
33
use crate::Side;
44
use rust_decimal::Decimal;
55

@@ -18,18 +18,18 @@ use rust_decimal::Decimal;
1818
/// # Example
1919
/// ```no_run
2020
/// use polymarket_rs::orders::calculate_market_price;
21-
/// use polymarket_rs::types::OrderSummary;
21+
/// use polymarket_rs::types::PriceLevel;
2222
/// use polymarket_rs::Side;
2323
/// use rust_decimal::Decimal;
2424
///
2525
/// let positions = vec![
26-
/// OrderSummary { price: Decimal::new(50, 2), size: Decimal::new(100, 0) },
27-
/// OrderSummary { price: Decimal::new(51, 2), size: Decimal::new(200, 0) },
26+
/// PriceLevel { price: Decimal::new(50, 2), size: Decimal::new(100, 0) },
27+
/// PriceLevel { price: Decimal::new(51, 2), size: Decimal::new(200, 0) },
2828
/// ];
2929
/// let price = calculate_market_price(&positions, Decimal::new(150, 0), Side::Buy).unwrap();
3030
/// ```
3131
pub fn calculate_market_price(
32-
positions: &[OrderSummary],
32+
positions: &[PriceLevel],
3333
shares_to_match: Decimal,
3434
side: Side,
3535
) -> Result<Decimal> {
@@ -72,8 +72,8 @@ mod tests {
7272
use super::*;
7373
use rust_decimal_macros::dec;
7474

75-
fn order(price: Decimal, size: Decimal) -> OrderSummary {
76-
OrderSummary { price, size }
75+
fn order(price: Decimal, size: Decimal) -> PriceLevel {
76+
PriceLevel { price, size }
7777
}
7878

7979
#[test]

0 commit comments

Comments
 (0)