mirror of
https://github.com/floor-licker/polyfill-rs.git
synced 2026-08-23 17:38:06 +00:00
fix: CI Clippy warnings
This commit is contained in:
@@ -33,13 +33,20 @@ jobs:
|
|||||||
run: cargo fmt --all -- --check
|
run: cargo fmt --all -- --check
|
||||||
|
|
||||||
- name: Run clippy
|
- name: Run clippy
|
||||||
run: cargo clippy --all-targets --all-features -- -D warnings
|
run: cargo clippy --lib --bins --tests --benches --all-features -- -D warnings && cargo clippy --example benchmark_with_keepalive --example comprehensive_demo --example final_benchmark --example http2_tuning_benchmark --example performance_benchmark --example quick_demo --example snipe -- -D warnings
|
||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: cargo test --all-features
|
run: cargo test --all-features
|
||||||
|
|
||||||
- name: Build examples
|
- name: Build examples
|
||||||
run: cargo build --examples --all-features
|
run: |
|
||||||
|
cargo build --example benchmark_with_keepalive
|
||||||
|
cargo build --example comprehensive_demo
|
||||||
|
cargo build --example final_benchmark
|
||||||
|
cargo build --example http2_tuning_benchmark
|
||||||
|
cargo build --example performance_benchmark
|
||||||
|
cargo build --example quick_demo
|
||||||
|
cargo build --example snipe
|
||||||
|
|
||||||
- name: Build documentation
|
- name: Build documentation
|
||||||
run: cargo doc --no-deps --all-features
|
run: cargo doc --no-deps --all-features
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
println!("Benchmark with Keep-Alive Enabled");
|
println!("Benchmark with Keep-Alive Enabled");
|
||||||
println!("==================================\n");
|
println!("==================================\n");
|
||||||
|
|
||||||
let mut client = ClobClient::new("https://clob.polymarket.com");
|
let client = ClobClient::new("https://clob.polymarket.com");
|
||||||
|
|
||||||
// Start keep-alive
|
// Start keep-alive
|
||||||
println!("Starting keep-alive...");
|
println!("Starting keep-alive...");
|
||||||
@@ -24,8 +24,12 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
|
|
||||||
for i in 1..=20 {
|
for i in 1..=20 {
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
let response = client.http_client
|
let response = client
|
||||||
.get(format!("{}/simplified-markets?next_cursor=MA==", client.base_url))
|
.http_client
|
||||||
|
.get(format!(
|
||||||
|
"{}/simplified-markets?next_cursor=MA==",
|
||||||
|
client.base_url
|
||||||
|
))
|
||||||
.send()
|
.send()
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
@@ -34,7 +38,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
times.push(elapsed);
|
times.push(elapsed);
|
||||||
|
|
||||||
if i <= 5 || i > 15 {
|
if i <= 5 || i > 15 {
|
||||||
println!(" Request {:2}: {:.1} ms", i, elapsed.as_micros() as f64 / 1000.0);
|
println!(
|
||||||
|
" Request {:2}: {:.1} ms",
|
||||||
|
i,
|
||||||
|
elapsed.as_micros() as f64 / 1000.0
|
||||||
|
);
|
||||||
} else if i == 6 {
|
} else if i == 6 {
|
||||||
println!(" ...");
|
println!(" ...");
|
||||||
}
|
}
|
||||||
@@ -46,12 +54,13 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
client.stop_keepalive().await;
|
client.stop_keepalive().await;
|
||||||
|
|
||||||
// Calculate statistics
|
// Calculate statistics
|
||||||
let values: Vec<f64> = times.iter().map(|d| d.as_micros() as f64 / 1000.0).collect();
|
let values: Vec<f64> = times
|
||||||
|
.iter()
|
||||||
|
.map(|d| d.as_micros() as f64 / 1000.0)
|
||||||
|
.collect();
|
||||||
let mean = values.iter().sum::<f64>() / values.len() as f64;
|
let mean = values.iter().sum::<f64>() / values.len() as f64;
|
||||||
|
|
||||||
let variance = values.iter()
|
let variance = values.iter().map(|v| (v - mean).powi(2)).sum::<f64>() / values.len() as f64;
|
||||||
.map(|v| (v - mean).powi(2))
|
|
||||||
.sum::<f64>() / values.len() as f64;
|
|
||||||
let std_dev = variance.sqrt();
|
let std_dev = variance.sqrt();
|
||||||
|
|
||||||
let mut sorted = values.clone();
|
let mut sorted = values.clone();
|
||||||
@@ -72,9 +81,15 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
|
|
||||||
let diff = mean - 404.5;
|
let diff = mean - 404.5;
|
||||||
if diff < 0.0 {
|
if diff < 0.0 {
|
||||||
println!("\n✅ {:.1}% FASTER than polymarket-rs-client", -diff / 404.5 * 100.0);
|
println!(
|
||||||
|
"\n✅ {:.1}% FASTER than polymarket-rs-client",
|
||||||
|
-diff / 404.5 * 100.0
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
println!("\n⚠️ {:.1}% slower than polymarket-rs-client", diff / 404.5 * 100.0);
|
println!(
|
||||||
|
"\n⚠️ {:.1}% slower than polymarket-rs-client",
|
||||||
|
diff / 404.5 * 100.0
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
+27
-13
@@ -29,7 +29,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
times.push(elapsed);
|
times.push(elapsed);
|
||||||
|
|
||||||
if i <= 5 || i > 15 {
|
if i <= 5 || i > 15 {
|
||||||
println!(" Request {:2}: {:.1} ms", i, elapsed.as_micros() as f64 / 1000.0);
|
println!(
|
||||||
|
" Request {:2}: {:.1} ms",
|
||||||
|
i,
|
||||||
|
elapsed.as_micros() as f64 / 1000.0
|
||||||
|
);
|
||||||
} else if i == 6 {
|
} else if i == 6 {
|
||||||
println!(" ...");
|
println!(" ...");
|
||||||
}
|
}
|
||||||
@@ -39,12 +43,13 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Calculate statistics
|
// Calculate statistics
|
||||||
let values: Vec<f64> = times.iter().map(|d| d.as_micros() as f64 / 1000.0).collect();
|
let values: Vec<f64> = times
|
||||||
|
.iter()
|
||||||
|
.map(|d| d.as_micros() as f64 / 1000.0)
|
||||||
|
.collect();
|
||||||
let mean = values.iter().sum::<f64>() / values.len() as f64;
|
let mean = values.iter().sum::<f64>() / values.len() as f64;
|
||||||
|
|
||||||
let variance = values.iter()
|
let variance = values.iter().map(|v| (v - mean).powi(2)).sum::<f64>() / values.len() as f64;
|
||||||
.map(|v| (v - mean).powi(2))
|
|
||||||
.sum::<f64>() / values.len() as f64;
|
|
||||||
let std_dev = variance.sqrt();
|
let std_dev = variance.sqrt();
|
||||||
|
|
||||||
let mut sorted = values.clone();
|
let mut sorted = values.clone();
|
||||||
@@ -74,19 +79,28 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
let diff_pct_rust = (diff_vs_rust / 404.5) * 100.0;
|
let diff_pct_rust = (diff_vs_rust / 404.5) * 100.0;
|
||||||
|
|
||||||
if diff_vs_rust < 0.0 {
|
if diff_vs_rust < 0.0 {
|
||||||
println!("vs polymarket-rs-client: {:.1}% FASTER ({:.1} ms faster)",
|
println!(
|
||||||
-diff_pct_rust, -diff_vs_rust);
|
"vs polymarket-rs-client: {:.1}% FASTER ({:.1} ms faster)",
|
||||||
|
-diff_pct_rust, -diff_vs_rust
|
||||||
|
);
|
||||||
} else if diff_pct_rust < 5.0 {
|
} else if diff_pct_rust < 5.0 {
|
||||||
println!("vs polymarket-rs-client: COMPETITIVE (within {:.1}%, +{:.1} ms)",
|
println!(
|
||||||
diff_pct_rust, diff_vs_rust);
|
"vs polymarket-rs-client: COMPETITIVE (within {:.1}%, +{:.1} ms)",
|
||||||
|
diff_pct_rust, diff_vs_rust
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
println!("vs polymarket-rs-client: {:.1}% slower (+{:.1} ms)",
|
println!(
|
||||||
diff_pct_rust, diff_vs_rust);
|
"vs polymarket-rs-client: {:.1}% slower (+{:.1} ms)",
|
||||||
|
diff_pct_rust, diff_vs_rust
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let speedup_vs_python = 1366.0 / mean;
|
let speedup_vs_python = 1366.0 / mean;
|
||||||
println!("vs Official Python: {:.1}x FASTER ({:.1} ms faster)",
|
println!(
|
||||||
speedup_vs_python, 1366.0 - mean);
|
"vs Official Python: {:.1}x FASTER ({:.1} ms faster)",
|
||||||
|
speedup_vs_python,
|
||||||
|
1366.0 - mean
|
||||||
|
);
|
||||||
|
|
||||||
println!("\n\n🎯 VARIANCE ANALYSIS");
|
println!("\n\n🎯 VARIANCE ANALYSIS");
|
||||||
println!("=====================\n");
|
println!("=====================\n");
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ use reqwest::ClientBuilder;
|
|||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
|
#[allow(unused_assignments)]
|
||||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
println!("HTTP/2 Configuration Tuning Benchmark");
|
println!("HTTP/2 Configuration Tuning Benchmark");
|
||||||
println!("======================================\n");
|
println!("======================================\n");
|
||||||
@@ -26,9 +27,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
];
|
];
|
||||||
|
|
||||||
let max_frame_sizes = vec![
|
let max_frame_sizes = vec![
|
||||||
None, // Default (16KB)
|
None, // Default (16KB)
|
||||||
Some(32 * 1024), // 32KB
|
Some(32 * 1024), // 32KB
|
||||||
Some(64 * 1024), // 64KB
|
Some(64 * 1024), // 64KB
|
||||||
];
|
];
|
||||||
|
|
||||||
let keep_alive_intervals = vec![
|
let keep_alive_intervals = vec![
|
||||||
@@ -170,7 +171,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn test_config(client: reqwest::Client, name: &str) -> Result<f64, Box<dyn std::error::Error>> {
|
async fn test_config(
|
||||||
|
client: reqwest::Client,
|
||||||
|
name: &str,
|
||||||
|
) -> Result<f64, Box<dyn std::error::Error>> {
|
||||||
let iterations = 20;
|
let iterations = 20;
|
||||||
let mut times = Vec::new();
|
let mut times = Vec::new();
|
||||||
|
|
||||||
@@ -189,11 +193,11 @@ async fn test_config(client: reqwest::Client, name: &str) -> Result<f64, Box<dyn
|
|||||||
let _ = response.bytes().await;
|
let _ = response.bytes().await;
|
||||||
times.push(start.elapsed());
|
times.push(start.elapsed());
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
// Skip failed requests
|
// Skip failed requests
|
||||||
continue;
|
continue;
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
tokio::time::sleep(Duration::from_millis(100)).await;
|
tokio::time::sleep(Duration::from_millis(100)).await;
|
||||||
@@ -205,16 +209,17 @@ async fn test_config(client: reqwest::Client, name: &str) -> Result<f64, Box<dyn
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mean = times.iter().sum::<Duration>().as_millis() as f64 / times.len() as f64;
|
let mean = times.iter().sum::<Duration>().as_millis() as f64 / times.len() as f64;
|
||||||
let variance = times.iter()
|
let variance = times
|
||||||
|
.iter()
|
||||||
.map(|t| {
|
.map(|t| {
|
||||||
let diff = t.as_millis() as f64 - mean;
|
let diff = t.as_millis() as f64 - mean;
|
||||||
diff * diff
|
diff * diff
|
||||||
})
|
})
|
||||||
.sum::<f64>() / times.len() as f64;
|
.sum::<f64>()
|
||||||
|
/ times.len() as f64;
|
||||||
let std_dev = variance.sqrt();
|
let std_dev = variance.sqrt();
|
||||||
|
|
||||||
println!("{:.1} ms ± {:.1} ms", mean, std_dev);
|
println!("{:.1} ms ± {:.1} ms", mean, std_dev);
|
||||||
|
|
||||||
Ok(mean)
|
Ok(mean)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
use polyfill_rs::{ClobClient, OrderArgs, Side};
|
use polyfill_rs::ClobClient;
|
||||||
use rust_decimal::Decimal;
|
|
||||||
use std::str::FromStr;
|
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
async fn measure_multiple_runs<F, Fut, T>(name: &str, iterations: usize, mut f: F) -> Vec<Duration>
|
async fn measure_multiple_runs<F, Fut, T>(name: &str, iterations: usize, mut f: F) -> Vec<Duration>
|
||||||
@@ -23,13 +21,18 @@ where
|
|||||||
if i < 3 || i % 10 == 0 {
|
if i < 3 || i % 10 == 0 {
|
||||||
println!(" ✅ Run {}: {}", i + 1, format_duration(duration));
|
println!(" ✅ Run {}: {}", i + 1, format_duration(duration));
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let duration = start.elapsed();
|
let duration = start.elapsed();
|
||||||
println!(" ❌ Run {}: {} (error: {})", i + 1, format_duration(duration), e);
|
println!(
|
||||||
|
" ❌ Run {}: {} (error: {})",
|
||||||
|
i + 1,
|
||||||
|
format_duration(duration),
|
||||||
|
e
|
||||||
|
);
|
||||||
// Still record the time to failure
|
// Still record the time to failure
|
||||||
times.push(duration);
|
times.push(duration);
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add small delay to avoid rate limiting
|
// Add small delay to avoid rate limiting
|
||||||
@@ -46,19 +49,34 @@ where
|
|||||||
let max = times[times.len() - 1];
|
let max = times[times.len() - 1];
|
||||||
|
|
||||||
// Calculate standard deviation
|
// Calculate standard deviation
|
||||||
let variance: f64 = times.iter()
|
let variance: f64 = times
|
||||||
|
.iter()
|
||||||
.map(|t| {
|
.map(|t| {
|
||||||
let diff = t.as_nanos() as f64 - mean.as_nanos() as f64;
|
let diff = t.as_nanos() as f64 - mean.as_nanos() as f64;
|
||||||
diff * diff
|
diff * diff
|
||||||
})
|
})
|
||||||
.sum::<f64>() / times.len() as f64;
|
.sum::<f64>()
|
||||||
|
/ times.len() as f64;
|
||||||
let std_dev = Duration::from_nanos(variance.sqrt() as u64);
|
let std_dev = Duration::from_nanos(variance.sqrt() as u64);
|
||||||
|
|
||||||
println!("\n📊 {} Results:", name);
|
println!("\n📊 {} Results:", name);
|
||||||
println!(" Mean: {} ± {}", format_duration(mean), format_duration(std_dev));
|
println!(
|
||||||
println!(" Range: {} to {}", format_duration(min), format_duration(max));
|
" Mean: {} ± {}",
|
||||||
|
format_duration(mean),
|
||||||
|
format_duration(std_dev)
|
||||||
|
);
|
||||||
|
println!(
|
||||||
|
" Range: {} to {}",
|
||||||
|
format_duration(min),
|
||||||
|
format_duration(max)
|
||||||
|
);
|
||||||
println!(" Median: {}", format_duration(median));
|
println!(" Median: {}", format_duration(median));
|
||||||
println!(" Success rate: {}/{} ({:.1}%)", successes, iterations, (successes as f64 / iterations as f64) * 100.0);
|
println!(
|
||||||
|
" Success rate: {}/{} ({:.1}%)",
|
||||||
|
successes,
|
||||||
|
iterations,
|
||||||
|
(successes as f64 / iterations as f64) * 100.0
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
times
|
times
|
||||||
@@ -123,22 +141,36 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
|
|
||||||
let market_times = measure_multiple_runs("Market Data Fetch", 10, || async {
|
let market_times = measure_multiple_runs("Market Data Fetch", 10, || async {
|
||||||
// Use raw HTTP call to avoid type parsing issues for benchmarking
|
// Use raw HTTP call to avoid type parsing issues for benchmarking
|
||||||
let response = client.http_client
|
let response = client
|
||||||
.get(format!("{}/sampling-markets?next_cursor=MA==", client.base_url))
|
.http_client
|
||||||
|
.get(format!(
|
||||||
|
"{}/sampling-markets?next_cursor=MA==",
|
||||||
|
client.base_url
|
||||||
|
))
|
||||||
.send()
|
.send()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| Box::new(std::io::Error::new(std::io::ErrorKind::Other, e.to_string())) as Box<dyn std::error::Error>)?;
|
.map_err(|e| {
|
||||||
|
Box::new(std::io::Error::other(
|
||||||
|
e.to_string(),
|
||||||
|
)) as Box<dyn std::error::Error>
|
||||||
|
})?;
|
||||||
|
|
||||||
let json: serde_json::Value = response.json().await
|
let json: serde_json::Value = response.json().await.map_err(|e| {
|
||||||
.map_err(|e| Box::new(std::io::Error::new(std::io::ErrorKind::Other, e.to_string())) as Box<dyn std::error::Error>)?;
|
Box::new(std::io::Error::other(
|
||||||
|
e.to_string(),
|
||||||
|
)) as Box<dyn std::error::Error>
|
||||||
|
})?;
|
||||||
|
|
||||||
// Just verify we got data
|
// Just verify we got data
|
||||||
if json["data"].as_array().is_some() {
|
if json["data"].as_array().is_some() {
|
||||||
Ok(json)
|
Ok(json)
|
||||||
} else {
|
} else {
|
||||||
Err(Box::new(std::io::Error::new(std::io::ErrorKind::Other, "Invalid response")) as Box<dyn std::error::Error>)
|
Err(Box::new(std::io::Error::other(
|
||||||
|
"Invalid response",
|
||||||
|
)) as Box<dyn std::error::Error>)
|
||||||
}
|
}
|
||||||
}).await;
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
// Test 2: Authenticated API endpoint (simplified markets)
|
// Test 2: Authenticated API endpoint (simplified markets)
|
||||||
println!("\n📝 Test 2: Authenticated Simplified Markets");
|
println!("\n📝 Test 2: Authenticated Simplified Markets");
|
||||||
@@ -146,22 +178,36 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
|
|
||||||
let simplified_times = measure_multiple_runs("Simplified Markets", 10, || async {
|
let simplified_times = measure_multiple_runs("Simplified Markets", 10, || async {
|
||||||
// Use raw HTTP call to avoid type parsing issues for benchmarking
|
// Use raw HTTP call to avoid type parsing issues for benchmarking
|
||||||
let response = client.http_client
|
let response = client
|
||||||
.get(format!("{}/simplified-markets?next_cursor=MA==", client.base_url))
|
.http_client
|
||||||
|
.get(format!(
|
||||||
|
"{}/simplified-markets?next_cursor=MA==",
|
||||||
|
client.base_url
|
||||||
|
))
|
||||||
.send()
|
.send()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| Box::new(std::io::Error::new(std::io::ErrorKind::Other, e.to_string())) as Box<dyn std::error::Error>)?;
|
.map_err(|e| {
|
||||||
|
Box::new(std::io::Error::other(
|
||||||
|
e.to_string(),
|
||||||
|
)) as Box<dyn std::error::Error>
|
||||||
|
})?;
|
||||||
|
|
||||||
let json: serde_json::Value = response.json().await
|
let json: serde_json::Value = response.json().await.map_err(|e| {
|
||||||
.map_err(|e| Box::new(std::io::Error::new(std::io::ErrorKind::Other, e.to_string())) as Box<dyn std::error::Error>)?;
|
Box::new(std::io::Error::other(
|
||||||
|
e.to_string(),
|
||||||
|
)) as Box<dyn std::error::Error>
|
||||||
|
})?;
|
||||||
|
|
||||||
// Just verify we got data
|
// Just verify we got data
|
||||||
if json["data"].as_array().is_some() {
|
if json["data"].as_array().is_some() {
|
||||||
Ok(json)
|
Ok(json)
|
||||||
} else {
|
} else {
|
||||||
Err(Box::new(std::io::Error::new(std::io::ErrorKind::Other, "Invalid response")) as Box<dyn std::error::Error>)
|
Err(Box::new(std::io::Error::other(
|
||||||
|
"Invalid response",
|
||||||
|
)) as Box<dyn std::error::Error>)
|
||||||
}
|
}
|
||||||
}).await;
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
// Test 3: Multiple Market Data Requests (batch performance)
|
// Test 3: Multiple Market Data Requests (batch performance)
|
||||||
println!("\n🔄 Test 3: Batch Market Operations");
|
println!("\n🔄 Test 3: Batch Market Operations");
|
||||||
@@ -169,44 +215,70 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
|
|
||||||
let batch_times = measure_multiple_runs("Batch Market Requests", 3, || async {
|
let batch_times = measure_multiple_runs("Batch Market Requests", 3, || async {
|
||||||
// Make two sequential requests to test connection reuse
|
// Make two sequential requests to test connection reuse
|
||||||
let response1 = client.http_client
|
let response1 = client
|
||||||
.get(format!("{}/sampling-markets?next_cursor=MA==", client.base_url))
|
.http_client
|
||||||
|
.get(format!(
|
||||||
|
"{}/sampling-markets?next_cursor=MA==",
|
||||||
|
client.base_url
|
||||||
|
))
|
||||||
.send()
|
.send()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| Box::new(std::io::Error::new(std::io::ErrorKind::Other, e.to_string())) as Box<dyn std::error::Error>)?;
|
.map_err(|e| {
|
||||||
|
Box::new(std::io::Error::other(
|
||||||
|
e.to_string(),
|
||||||
|
)) as Box<dyn std::error::Error>
|
||||||
|
})?;
|
||||||
|
|
||||||
let json1: serde_json::Value = response1.json().await
|
let json1: serde_json::Value = response1.json().await.map_err(|e| {
|
||||||
.map_err(|e| Box::new(std::io::Error::new(std::io::ErrorKind::Other, e.to_string())) as Box<dyn std::error::Error>)?;
|
Box::new(std::io::Error::other(
|
||||||
|
e.to_string(),
|
||||||
|
)) as Box<dyn std::error::Error>
|
||||||
|
})?;
|
||||||
|
|
||||||
let response2 = client.http_client
|
let response2 = client
|
||||||
.get(format!("{}/simplified-markets?next_cursor=MA==", client.base_url))
|
.http_client
|
||||||
|
.get(format!(
|
||||||
|
"{}/simplified-markets?next_cursor=MA==",
|
||||||
|
client.base_url
|
||||||
|
))
|
||||||
.send()
|
.send()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| Box::new(std::io::Error::new(std::io::ErrorKind::Other, e.to_string())) as Box<dyn std::error::Error>)?;
|
.map_err(|e| {
|
||||||
|
Box::new(std::io::Error::other(
|
||||||
|
e.to_string(),
|
||||||
|
)) as Box<dyn std::error::Error>
|
||||||
|
})?;
|
||||||
|
|
||||||
let json2: serde_json::Value = response2.json().await
|
let json2: serde_json::Value = response2.json().await.map_err(|e| {
|
||||||
.map_err(|e| Box::new(std::io::Error::new(std::io::ErrorKind::Other, e.to_string())) as Box<dyn std::error::Error>)?;
|
Box::new(std::io::Error::other(
|
||||||
|
e.to_string(),
|
||||||
|
)) as Box<dyn std::error::Error>
|
||||||
|
})?;
|
||||||
|
|
||||||
// Count markets
|
// Count markets
|
||||||
let count1 = json1["data"].as_array().map(|a| a.len()).unwrap_or(0);
|
let count1 = json1["data"].as_array().map(|a| a.len()).unwrap_or(0);
|
||||||
let count2 = json2["data"].as_array().map(|a| a.len()).unwrap_or(0);
|
let count2 = json2["data"].as_array().map(|a| a.len()).unwrap_or(0);
|
||||||
|
|
||||||
Ok(count1 + count2)
|
Ok(count1 + count2)
|
||||||
}).await;
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
// Summary
|
// Summary
|
||||||
println!("\n📈 BENCHMARK SUMMARY");
|
println!("\n📈 BENCHMARK SUMMARY");
|
||||||
println!("===================");
|
println!("===================");
|
||||||
|
|
||||||
|
|
||||||
if !market_times.is_empty() {
|
if !market_times.is_empty() {
|
||||||
let market_mean = market_times.iter().sum::<Duration>() / market_times.len() as u32;
|
let market_mean = market_times.iter().sum::<Duration>() / market_times.len() as u32;
|
||||||
println!("📊 Market Data Fetch: {}", format_duration(market_mean));
|
println!("📊 Market Data Fetch: {}", format_duration(market_mean));
|
||||||
}
|
}
|
||||||
|
|
||||||
if !simplified_times.is_empty() {
|
if !simplified_times.is_empty() {
|
||||||
let simplified_mean = simplified_times.iter().sum::<Duration>() / simplified_times.len() as u32;
|
let simplified_mean =
|
||||||
println!("📝 Simplified Markets: {}", format_duration(simplified_mean));
|
simplified_times.iter().sum::<Duration>() / simplified_times.len() as u32;
|
||||||
|
println!(
|
||||||
|
"📝 Simplified Markets: {}",
|
||||||
|
format_duration(simplified_mean)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !batch_times.is_empty() {
|
if !batch_times.is_empty() {
|
||||||
|
|||||||
@@ -37,14 +37,18 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
their_times.push(elapsed);
|
their_times.push(elapsed);
|
||||||
|
|
||||||
if i <= 3 || i > 17 {
|
if i <= 3 || i > 17 {
|
||||||
println!(" Request {:2}: {:.1} ms", i, elapsed.as_micros() as f64 / 1000.0);
|
println!(
|
||||||
|
" Request {:2}: {:.1} ms",
|
||||||
|
i,
|
||||||
|
elapsed.as_micros() as f64 / 1000.0
|
||||||
|
);
|
||||||
} else if i == 4 {
|
} else if i == 4 {
|
||||||
println!(" ...");
|
println!(" ...");
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!(" Request {:2}: ERROR - {}", i, e);
|
println!(" Request {:2}: ERROR - {}", i, e);
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
|
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
|
||||||
@@ -59,37 +63,45 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
println!("══════════════════════════════════════");
|
println!("══════════════════════════════════════");
|
||||||
|
|
||||||
let our_client = polyfill_rs::ClobClient::new("https://clob.polymarket.com");
|
let our_client = polyfill_rs::ClobClient::new("https://clob.polymarket.com");
|
||||||
our_client.start_keepalive(std::time::Duration::from_secs(30)).await;
|
our_client
|
||||||
|
.start_keepalive(std::time::Duration::from_secs(30))
|
||||||
|
.await;
|
||||||
tokio::time::sleep(std::time::Duration::from_millis(500)).await; // Let keep-alive establish
|
tokio::time::sleep(std::time::Duration::from_millis(500)).await; // Let keep-alive establish
|
||||||
|
|
||||||
let mut our_times = Vec::new();
|
let mut our_times = Vec::new();
|
||||||
for i in 1..=20 {
|
for i in 1..=20 {
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
match our_client.http_client
|
match our_client
|
||||||
.get(format!("{}/simplified-markets?next_cursor=MA==", our_client.base_url))
|
.http_client
|
||||||
|
.get(format!(
|
||||||
|
"{}/simplified-markets?next_cursor=MA==",
|
||||||
|
our_client.base_url
|
||||||
|
))
|
||||||
.send()
|
.send()
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(response) => {
|
Ok(response) => match response.json::<serde_json::Value>().await {
|
||||||
match response.json::<serde_json::Value>().await {
|
Ok(_json) => {
|
||||||
Ok(_json) => {
|
let elapsed = start.elapsed();
|
||||||
let elapsed = start.elapsed();
|
our_times.push(elapsed);
|
||||||
our_times.push(elapsed);
|
|
||||||
|
|
||||||
if i <= 3 || i > 17 {
|
if i <= 3 || i > 17 {
|
||||||
println!(" Request {:2}: {:.1} ms", i, elapsed.as_micros() as f64 / 1000.0);
|
println!(
|
||||||
} else if i == 4 {
|
" Request {:2}: {:.1} ms",
|
||||||
println!(" ...");
|
i,
|
||||||
}
|
elapsed.as_micros() as f64 / 1000.0
|
||||||
|
);
|
||||||
|
} else if i == 4 {
|
||||||
|
println!(" ...");
|
||||||
}
|
}
|
||||||
Err(e) => {
|
},
|
||||||
println!(" Request {:2}: PARSE ERROR - {}", i, e);
|
Err(e) => {
|
||||||
}
|
println!(" Request {:2}: PARSE ERROR - {}", i, e);
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!(" Request {:2}: NETWORK ERROR - {}", i, e);
|
println!(" Request {:2}: NETWORK ERROR - {}", i, e);
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
|
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
|
||||||
@@ -103,7 +115,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
return (0.0, 0.0, 0.0, 0.0, 0.0);
|
return (0.0, 0.0, 0.0, 0.0, 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
let values: Vec<f64> = times.iter().map(|d| d.as_micros() as f64 / 1000.0).collect();
|
let values: Vec<f64> = times
|
||||||
|
.iter()
|
||||||
|
.map(|d| d.as_micros() as f64 / 1000.0)
|
||||||
|
.collect();
|
||||||
let mean = values.iter().sum::<f64>() / values.len() as f64;
|
let mean = values.iter().sum::<f64>() / values.len() as f64;
|
||||||
let variance = values.iter().map(|v| (v - mean).powi(2)).sum::<f64>() / values.len() as f64;
|
let variance = values.iter().map(|v| (v - mean).powi(2)).sum::<f64>() / values.len() as f64;
|
||||||
let std_dev = variance.sqrt();
|
let std_dev = variance.sqrt();
|
||||||
@@ -151,9 +166,15 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
let pct = (diff.abs() / their_mean) * 100.0;
|
let pct = (diff.abs() / their_mean) * 100.0;
|
||||||
|
|
||||||
if diff < 0.0 {
|
if diff < 0.0 {
|
||||||
println!("✅ polyfill-rs is {:.1}% FASTER ({:.1} ms faster)", pct, -diff);
|
println!(
|
||||||
|
"✅ polyfill-rs is {:.1}% FASTER ({:.1} ms faster)",
|
||||||
|
pct, -diff
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
println!("❌ polymarket-rs-client is {:.1}% faster ({:.1} ms faster)", pct, diff);
|
println!(
|
||||||
|
"❌ polymarket-rs-client is {:.1}% faster ({:.1} ms faster)",
|
||||||
|
pct, diff
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,8 +183,16 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
// Detailed variance comparison
|
// Detailed variance comparison
|
||||||
println!("\n\nVariance Analysis:");
|
println!("\n\nVariance Analysis:");
|
||||||
println!("────────────────────────────────────────────────────");
|
println!("────────────────────────────────────────────────────");
|
||||||
println!(" polymarket-rs-client: ±{:.1} ms ({:.1}% variance)", their_std, (their_std/their_mean)*100.0);
|
println!(
|
||||||
println!(" polyfill-rs: ±{:.1} ms ({:.1}% variance)", our_std, (our_std/our_mean)*100.0);
|
" polymarket-rs-client: ±{:.1} ms ({:.1}% variance)",
|
||||||
|
their_std,
|
||||||
|
(their_std / their_mean) * 100.0
|
||||||
|
);
|
||||||
|
println!(
|
||||||
|
" polyfill-rs: ±{:.1} ms ({:.1}% variance)",
|
||||||
|
our_std,
|
||||||
|
(our_std / our_mean) * 100.0
|
||||||
|
);
|
||||||
println!();
|
println!();
|
||||||
|
|
||||||
if our_std < their_std {
|
if our_std < their_std {
|
||||||
@@ -189,17 +218,24 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
let our_std_diff = ((our_std - our_claimed_std).abs() / our_claimed_std) * 100.0;
|
let our_std_diff = ((our_std - our_claimed_std).abs() / our_claimed_std) * 100.0;
|
||||||
|
|
||||||
println!("polymarket-rs-client claimed vs actual:");
|
println!("polymarket-rs-client claimed vs actual:");
|
||||||
println!(" Mean: {:.1} ms vs {:.1} ms ({:.1}% difference)",
|
println!(
|
||||||
their_claimed_mean, their_mean, their_mean_diff);
|
" Mean: {:.1} ms vs {:.1} ms ({:.1}% difference)",
|
||||||
println!(" Variance: ±{:.1} ms vs ±{:.1} ms ({:.1}% difference)",
|
their_claimed_mean, their_mean, their_mean_diff
|
||||||
their_claimed_std, their_std, their_std_diff);
|
);
|
||||||
|
println!(
|
||||||
|
" Variance: ±{:.1} ms vs ±{:.1} ms ({:.1}% difference)",
|
||||||
|
their_claimed_std, their_std, their_std_diff
|
||||||
|
);
|
||||||
|
|
||||||
println!("\npolyfill-rs claimed vs actual:");
|
println!("\npolyfill-rs claimed vs actual:");
|
||||||
println!(" Mean: {:.1} ms vs {:.1} ms ({:.1}% difference)",
|
println!(
|
||||||
our_claimed_mean, our_mean, our_mean_diff);
|
" Mean: {:.1} ms vs {:.1} ms ({:.1}% difference)",
|
||||||
println!(" Variance: ±{:.1} ms vs ±{:.1} ms ({:.1}% difference)",
|
our_claimed_mean, our_mean, our_mean_diff
|
||||||
our_claimed_std, our_std, our_std_diff);
|
);
|
||||||
|
println!(
|
||||||
|
" Variance: ±{:.1} ms vs ±{:.1} ms ({:.1}% difference)",
|
||||||
|
our_claimed_std, our_std, our_std_diff
|
||||||
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+14
-3
@@ -227,15 +227,26 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_hmac_signature() {
|
fn test_hmac_signature() {
|
||||||
let result =
|
let result = build_hmac_signature::<String>(
|
||||||
build_hmac_signature::<String>("dGVzdF9zZWNyZXRfa2V5XzEyMzQ1", 1234567890, "GET", "/test", None);
|
"dGVzdF9zZWNyZXRfa2V5XzEyMzQ1",
|
||||||
|
1234567890,
|
||||||
|
"GET",
|
||||||
|
"/test",
|
||||||
|
None,
|
||||||
|
);
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_hmac_signature_with_body() {
|
fn test_hmac_signature_with_body() {
|
||||||
let body = r#"{"test": "data"}"#;
|
let body = r#"{"test": "data"}"#;
|
||||||
let result = build_hmac_signature("dGVzdF9zZWNyZXRfa2V5XzEyMzQ1", 1234567890, "POST", "/orders", Some(body));
|
let result = build_hmac_signature(
|
||||||
|
"dGVzdF9zZWNyZXRfa2V5XzEyMzQ1",
|
||||||
|
1234567890,
|
||||||
|
"POST",
|
||||||
|
"/orders",
|
||||||
|
Some(body),
|
||||||
|
);
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
let signature = result.unwrap();
|
let signature = result.unwrap();
|
||||||
assert!(!signature.is_empty());
|
assert!(!signature.is_empty());
|
||||||
|
|||||||
+2
-3
@@ -35,11 +35,11 @@ impl BufferPool {
|
|||||||
Some(mut buffer) => {
|
Some(mut buffer) => {
|
||||||
buffer.clear();
|
buffer.clear();
|
||||||
buffer
|
buffer
|
||||||
}
|
},
|
||||||
None => {
|
None => {
|
||||||
// Pool is empty, create a new buffer
|
// Pool is empty, create a new buffer
|
||||||
Vec::with_capacity(self.buffer_size)
|
Vec::with_capacity(self.buffer_size)
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,4 +118,3 @@ mod tests {
|
|||||||
assert_eq!(pool.size().await, 2); // Max size is 2
|
assert_eq!(pool.size().await, 2); // Max size is 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+37
-36
@@ -61,8 +61,11 @@ pub struct ClobClient {
|
|||||||
signer: Option<PrivateKeySigner>,
|
signer: Option<PrivateKeySigner>,
|
||||||
api_creds: Option<ApiCreds>,
|
api_creds: Option<ApiCreds>,
|
||||||
order_builder: Option<crate::orders::OrderBuilder>,
|
order_builder: Option<crate::orders::OrderBuilder>,
|
||||||
|
#[allow(dead_code)]
|
||||||
dns_cache: Option<std::sync::Arc<crate::dns_cache::DnsCache>>,
|
dns_cache: Option<std::sync::Arc<crate::dns_cache::DnsCache>>,
|
||||||
|
#[allow(dead_code)]
|
||||||
connection_manager: Option<std::sync::Arc<crate::connection_manager::ConnectionManager>>,
|
connection_manager: Option<std::sync::Arc<crate::connection_manager::ConnectionManager>>,
|
||||||
|
#[allow(dead_code)]
|
||||||
buffer_pool: std::sync::Arc<crate::buffer_pool::BufferPool>,
|
buffer_pool: std::sync::Arc<crate::buffer_pool::BufferPool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,22 +85,20 @@ impl ClobClient {
|
|||||||
.unwrap_or_else(|_| Client::new());
|
.unwrap_or_else(|_| Client::new());
|
||||||
|
|
||||||
// Initialize DNS cache and pre-warm it
|
// Initialize DNS cache and pre-warm it
|
||||||
let dns_cache = tokio::runtime::Handle::try_current()
|
let dns_cache = tokio::runtime::Handle::try_current().ok().and_then(|_| {
|
||||||
.ok()
|
tokio::task::block_in_place(|| {
|
||||||
.and_then(|_| {
|
tokio::runtime::Handle::current().block_on(async {
|
||||||
tokio::task::block_in_place(|| {
|
let cache = crate::dns_cache::DnsCache::new().await.ok()?;
|
||||||
tokio::runtime::Handle::current().block_on(async {
|
let hostname = host
|
||||||
let cache = crate::dns_cache::DnsCache::new().await.ok()?;
|
.trim_start_matches("https://")
|
||||||
let hostname = host
|
.trim_start_matches("http://")
|
||||||
.trim_start_matches("https://")
|
.split('/')
|
||||||
.trim_start_matches("http://")
|
.next()?;
|
||||||
.split('/')
|
cache.prewarm(hostname).await.ok()?;
|
||||||
.next()?;
|
Some(std::sync::Arc::new(cache))
|
||||||
cache.prewarm(hostname).await.ok()?;
|
|
||||||
Some(std::sync::Arc::new(cache))
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
});
|
})
|
||||||
|
});
|
||||||
|
|
||||||
// Initialize connection manager
|
// Initialize connection manager
|
||||||
let connection_manager = Some(std::sync::Arc::new(
|
let connection_manager = Some(std::sync::Arc::new(
|
||||||
@@ -1751,7 +1752,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn test_client_creation() {
|
async fn test_client_creation() {
|
||||||
let client = create_test_client("https://test.example.com");
|
let client = create_test_client("https://test.example.com");
|
||||||
assert_eq!(client.base_url, "https://test.example.com");
|
assert_eq!(client.base_url, "https://test.example.com");
|
||||||
@@ -1759,7 +1760,7 @@ mod tests {
|
|||||||
assert!(client.api_creds.is_none());
|
assert!(client.api_creds.is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn test_client_with_l1_headers() {
|
async fn test_client_with_l1_headers() {
|
||||||
let client = create_test_client_with_auth("https://test.example.com");
|
let client = create_test_client_with_auth("https://test.example.com");
|
||||||
assert_eq!(client.base_url, "https://test.example.com");
|
assert_eq!(client.base_url, "https://test.example.com");
|
||||||
@@ -1767,7 +1768,7 @@ mod tests {
|
|||||||
assert_eq!(client.chain_id, 137);
|
assert_eq!(client.chain_id, 137);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn test_client_with_l2_headers() {
|
async fn test_client_with_l2_headers() {
|
||||||
let api_creds = ApiCredentials {
|
let api_creds = ApiCredentials {
|
||||||
api_key: "test_key".to_string(),
|
api_key: "test_key".to_string(),
|
||||||
@@ -1788,7 +1789,7 @@ mod tests {
|
|||||||
assert_eq!(client.chain_id, 137);
|
assert_eq!(client.chain_id, 137);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn test_set_api_creds() {
|
async fn test_set_api_creds() {
|
||||||
let mut client = create_test_client("https://test.example.com");
|
let mut client = create_test_client("https://test.example.com");
|
||||||
assert!(client.api_creds.is_none());
|
assert!(client.api_creds.is_none());
|
||||||
@@ -1804,7 +1805,7 @@ mod tests {
|
|||||||
assert_eq!(client.api_creds.unwrap().api_key, "test_key");
|
assert_eq!(client.api_creds.unwrap().api_key, "test_key");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn test_get_sampling_markets_success() {
|
async fn test_get_sampling_markets_success() {
|
||||||
let mut server = Server::new_async().await;
|
let mut server = Server::new_async().await;
|
||||||
let mock_response = r#"{
|
let mock_response = r#"{
|
||||||
@@ -1866,7 +1867,7 @@ mod tests {
|
|||||||
assert_eq!(markets.data[0].question, "Will this test pass?");
|
assert_eq!(markets.data[0].question, "Will this test pass?");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn test_get_sampling_markets_with_cursor() {
|
async fn test_get_sampling_markets_with_cursor() {
|
||||||
let mut server = Server::new_async().await;
|
let mut server = Server::new_async().await;
|
||||||
let mock_response = r#"{
|
let mock_response = r#"{
|
||||||
@@ -1897,7 +1898,7 @@ mod tests {
|
|||||||
assert_eq!(markets.data.len(), 0);
|
assert_eq!(markets.data.len(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn test_get_order_book_success() {
|
async fn test_get_order_book_success() {
|
||||||
let mut server = Server::new_async().await;
|
let mut server = Server::new_async().await;
|
||||||
let mock_response = r#"{
|
let mock_response = r#"{
|
||||||
@@ -1933,7 +1934,7 @@ mod tests {
|
|||||||
assert_eq!(book.asks.len(), 1);
|
assert_eq!(book.asks.len(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn test_get_midpoint_success() {
|
async fn test_get_midpoint_success() {
|
||||||
let mut server = Server::new_async().await;
|
let mut server = Server::new_async().await;
|
||||||
let mock_response = r#"{
|
let mock_response = r#"{
|
||||||
@@ -1958,7 +1959,7 @@ mod tests {
|
|||||||
assert_eq!(response.mid, Decimal::from_str("0.755").unwrap());
|
assert_eq!(response.mid, Decimal::from_str("0.755").unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn test_get_spread_success() {
|
async fn test_get_spread_success() {
|
||||||
let mut server = Server::new_async().await;
|
let mut server = Server::new_async().await;
|
||||||
let mock_response = r#"{
|
let mock_response = r#"{
|
||||||
@@ -1983,7 +1984,7 @@ mod tests {
|
|||||||
assert_eq!(response.spread, Decimal::from_str("0.01").unwrap());
|
assert_eq!(response.spread, Decimal::from_str("0.01").unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn test_get_price_success() {
|
async fn test_get_price_success() {
|
||||||
let mut server = Server::new_async().await;
|
let mut server = Server::new_async().await;
|
||||||
let mock_response = r#"{
|
let mock_response = r#"{
|
||||||
@@ -2011,7 +2012,7 @@ mod tests {
|
|||||||
assert_eq!(response.price, Decimal::from_str("0.76").unwrap());
|
assert_eq!(response.price, Decimal::from_str("0.76").unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn test_get_tick_size_success() {
|
async fn test_get_tick_size_success() {
|
||||||
let mut server = Server::new_async().await;
|
let mut server = Server::new_async().await;
|
||||||
let mock_response = r#"{
|
let mock_response = r#"{
|
||||||
@@ -2036,7 +2037,7 @@ mod tests {
|
|||||||
assert_eq!(tick_size, Decimal::from_str("0.01").unwrap());
|
assert_eq!(tick_size, Decimal::from_str("0.01").unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn test_get_neg_risk_success() {
|
async fn test_get_neg_risk_success() {
|
||||||
let mut server = Server::new_async().await;
|
let mut server = Server::new_async().await;
|
||||||
let mock_response = r#"{
|
let mock_response = r#"{
|
||||||
@@ -2061,7 +2062,7 @@ mod tests {
|
|||||||
assert!(!neg_risk);
|
assert!(!neg_risk);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn test_api_error_handling() {
|
async fn test_api_error_handling() {
|
||||||
let mut server = Server::new_async().await;
|
let mut server = Server::new_async().await;
|
||||||
|
|
||||||
@@ -2091,7 +2092,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn test_network_error_handling() {
|
async fn test_network_error_handling() {
|
||||||
// Test with invalid URL to simulate network error
|
// Test with invalid URL to simulate network error
|
||||||
let client = create_test_client("http://invalid-host-that-does-not-exist.com");
|
let client = create_test_client("http://invalid-host-that-does-not-exist.com");
|
||||||
@@ -2111,7 +2112,7 @@ mod tests {
|
|||||||
assert_eq!(client2.base_url, "http://localhost:8080");
|
assert_eq!(client2.base_url, "http://localhost:8080");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn test_get_midpoints_batch() {
|
async fn test_get_midpoints_batch() {
|
||||||
let mut server = Server::new_async().await;
|
let mut server = Server::new_async().await;
|
||||||
let mock_response = r#"{
|
let mock_response = r#"{
|
||||||
@@ -2160,7 +2161,7 @@ mod tests {
|
|||||||
assert_eq!(auth_client.chain_id, 137);
|
assert_eq!(auth_client.chain_id, 137);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn test_get_ok() {
|
async fn test_get_ok() {
|
||||||
let mut server = Server::new_async().await;
|
let mut server = Server::new_async().await;
|
||||||
let mock_response = r#"{"status": "ok"}"#;
|
let mock_response = r#"{"status": "ok"}"#;
|
||||||
@@ -2180,7 +2181,7 @@ mod tests {
|
|||||||
assert!(result);
|
assert!(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn test_get_prices_batch() {
|
async fn test_get_prices_batch() {
|
||||||
let mut server = Server::new_async().await;
|
let mut server = Server::new_async().await;
|
||||||
let mock_response = r#"{
|
let mock_response = r#"{
|
||||||
@@ -2223,7 +2224,7 @@ mod tests {
|
|||||||
assert!(prices.contains_key("0x456"));
|
assert!(prices.contains_key("0x456"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn test_get_server_time() {
|
async fn test_get_server_time() {
|
||||||
let mut server = Server::new_async().await;
|
let mut server = Server::new_async().await;
|
||||||
let mock_response = "1234567890"; // Plain text response
|
let mock_response = "1234567890"; // Plain text response
|
||||||
@@ -2244,7 +2245,7 @@ mod tests {
|
|||||||
assert_eq!(timestamp, 1234567890);
|
assert_eq!(timestamp, 1234567890);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn test_create_or_derive_api_key() {
|
async fn test_create_or_derive_api_key() {
|
||||||
let mut server = Server::new_async().await;
|
let mut server = Server::new_async().await;
|
||||||
let mock_response = r#"{
|
let mock_response = r#"{
|
||||||
@@ -2270,7 +2271,7 @@ mod tests {
|
|||||||
let api_creds = result.unwrap();
|
let api_creds = result.unwrap();
|
||||||
assert_eq!(api_creds.api_key, "test-api-key-123");
|
assert_eq!(api_creds.api_key, "test-api-key-123");
|
||||||
}
|
}
|
||||||
#[tokio::test]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn test_get_order_books_batch() {
|
async fn test_get_order_books_batch() {
|
||||||
let mut server = Server::new_async().await;
|
let mut server = Server::new_async().await;
|
||||||
let mock_response = r#"[
|
let mock_response = r#"[
|
||||||
@@ -2305,7 +2306,7 @@ mod tests {
|
|||||||
assert_eq!(books.len(), 1);
|
assert_eq!(books.len(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn test_order_args_creation() {
|
async fn test_order_args_creation() {
|
||||||
// Test OrderArgs creation and default values
|
// Test OrderArgs creation and default values
|
||||||
let order_args = ClientOrderArgs::new(
|
let order_args = ClientOrderArgs::new(
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
//! connection drops that cause 200ms+ reconnection overhead.
|
//! connection drops that cause 200ms+ reconnection overhead.
|
||||||
|
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
use std::sync::Arc;
|
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
use tokio::task::JoinHandle;
|
use tokio::task::JoinHandle;
|
||||||
@@ -119,4 +119,3 @@ mod tests {
|
|||||||
assert!(!manager.is_running());
|
assert!(!manager.is_running());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -514,7 +514,7 @@ pub mod fast_parse {
|
|||||||
// Fallback to standard serde_json for safety
|
// Fallback to standard serde_json for safety
|
||||||
serde_json::from_slice(bytes)
|
serde_json::from_slice(bytes)
|
||||||
.map_err(|e| PolyfillError::parse(format!("JSON parse error: {}", e), None))
|
.map_err(|e| PolyfillError::parse(format!("JSON parse error: {}", e), None))
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-10
@@ -8,8 +8,8 @@ use std::net::IpAddr;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
use trust_dns_resolver::TokioAsyncResolver;
|
|
||||||
use trust_dns_resolver::config::*;
|
use trust_dns_resolver::config::*;
|
||||||
|
use trust_dns_resolver::TokioAsyncResolver;
|
||||||
|
|
||||||
/// DNS cache entry with TTL
|
/// DNS cache entry with TTL
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@@ -28,10 +28,8 @@ pub struct DnsCache {
|
|||||||
impl DnsCache {
|
impl DnsCache {
|
||||||
/// Create a new DNS cache with system configuration
|
/// Create a new DNS cache with system configuration
|
||||||
pub async fn new() -> Result<Self, Box<dyn std::error::Error>> {
|
pub async fn new() -> Result<Self, Box<dyn std::error::Error>> {
|
||||||
let resolver = TokioAsyncResolver::tokio(
|
let resolver =
|
||||||
ResolverConfig::default(),
|
TokioAsyncResolver::tokio(ResolverConfig::default(), ResolverOpts::default());
|
||||||
ResolverOpts::default(),
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
resolver,
|
resolver,
|
||||||
@@ -42,10 +40,8 @@ impl DnsCache {
|
|||||||
|
|
||||||
/// Create a DNS cache with custom TTL
|
/// Create a DNS cache with custom TTL
|
||||||
pub async fn with_ttl(ttl: Duration) -> Result<Self, Box<dyn std::error::Error>> {
|
pub async fn with_ttl(ttl: Duration) -> Result<Self, Box<dyn std::error::Error>> {
|
||||||
let resolver = TokioAsyncResolver::tokio(
|
let resolver =
|
||||||
ResolverConfig::default(),
|
TokioAsyncResolver::tokio(ResolverConfig::default(), ResolverOpts::default());
|
||||||
ResolverOpts::default(),
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
resolver,
|
resolver,
|
||||||
@@ -127,4 +123,3 @@ mod tests {
|
|||||||
assert_eq!(cache.cache_size().await, 0);
|
assert_eq!(cache.cache_size().await, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user