use std::time::Duration;
use reqwest::Method;
use crate::rate_limit::{Matching, RateLimiter, WindowQuotaTable};
const TEN_SECONDS: Duration = Duration::from_secs(10);
const TEN_MINUTES: Duration = Duration::from_secs(600);
fn dual(
table: &mut WindowQuotaTable,
pattern: &'static str,
method: Method,
burst: (u32, Duration),
sustained: (u32, Duration),
) {
let buckets = [
table.bucket(burst.0, burst.1),
table.bucket(sustained.0, sustained.1),
];
table.row(Matching::Prefix, pattern, Some(method), &buckets);
}
pub fn clob_limits() -> RateLimiter {
let get = Some(Method::GET);
let mut table = WindowQuotaTable::new(9_000, TEN_SECONDS);
let ledger_group = table.bucket(900, TEN_SECONDS);
table
.prefix("/balance-allowance/update", None, 50, TEN_SECONDS)
.prefix("/balance-allowance", None, 200, TEN_SECONDS);
for (pattern, method, burst, sustained) in [
("/order", Method::POST, 5_000, 120_000),
("/order", Method::DELETE, 5_000, 120_000),
("/orders", Method::POST, 2_000, 21_000),
("/orders", Method::DELETE, 2_000, 15_000),
("/cancel-all", Method::DELETE, 250, 6_000),
("/cancel-market-orders", Method::DELETE, 1_500, 21_000),
] {
dual(
&mut table,
pattern,
method,
(burst, TEN_SECONDS),
(sustained, TEN_MINUTES),
);
}
let notifications = table.bucket(125, TEN_SECONDS);
table
.row(
Matching::Prefix,
"/notifications",
None,
&[ledger_group, notifications],
)
.row(Matching::Prefix, "/trades", get.clone(), &[ledger_group])
.row(Matching::Prefix, "/orders", get.clone(), &[ledger_group])
.row(Matching::Prefix, "/order", get, &[ledger_group]);
table
.prefix("/data/orders", None, 500, TEN_SECONDS)
.prefix("/data/trades", None, 500, TEN_SECONDS)
.prefix("/data", None, 500, TEN_SECONDS)
.prefix("/auth", None, 100, TEN_SECONDS)
.prefix("/prices-history", None, 1_000, TEN_SECONDS)
.prefix("/book", None, 1_500, TEN_SECONDS)
.prefix("/books", None, 500, TEN_SECONDS)
.prefix("/price", None, 1_500, TEN_SECONDS)
.prefix("/prices", None, 500, TEN_SECONDS)
.prefix("/midpoint", None, 1_500, TEN_SECONDS)
.prefix("/midpoints", None, 500, TEN_SECONDS)
.prefix("/tick-size", None, 200, TEN_SECONDS)
.prefix("/ok", None, 100, TEN_SECONDS)
.prefix("/markets", None, 1_500, TEN_SECONDS)
.prefix("/neg-risk", None, 1_500, TEN_SECONDS);
table.build()
}
pub fn gamma_limits() -> RateLimiter {
let mut table = WindowQuotaTable::new(4_000, TEN_SECONDS);
table
.prefix("/comments", None, 200, TEN_SECONDS)
.prefix("/tags", None, 200, TEN_SECONDS)
.prefix("/markets", None, 300, TEN_SECONDS)
.prefix("/public-search", None, 350, TEN_SECONDS)
.prefix("/events", None, 500, TEN_SECONDS)
.prefix("/status", None, 100, TEN_SECONDS);
table.build()
}
pub fn data_limits() -> RateLimiter {
let mut table = WindowQuotaTable::new(1_000, TEN_SECONDS);
table
.prefix("/closed-positions", None, 150, TEN_SECONDS)
.prefix("/positions", None, 150, TEN_SECONDS)
.prefix("/trades", None, 200, TEN_SECONDS)
.prefix("/user-pnl", None, 200, TEN_SECONDS)
.prefix("/v2/positions/combos", None, 400, TEN_SECONDS)
.prefix("/v2/positions", None, 200, TEN_SECONDS)
.prefix("/v2/trades", None, 200, TEN_SECONDS)
.prefix("/v2/activity", None, 400, TEN_SECONDS)
.prefix("/v2/user-pnl", None, 400, TEN_SECONDS)
.prefix("/v2/holders", None, 400, TEN_SECONDS)
.prefix("/", None, 100, TEN_SECONDS);
table.build()
}
pub fn relay_limits() -> RateLimiter {
WindowQuotaTable::new(25, Duration::from_secs(60)).build()
}
pub fn perps_limits() -> RateLimiter {
const PIN_KLINES: u32 = 30;
const PIN_TRADES: u32 = 10;
const PIN_PORTFOLIO: u32 = 30;
const PIN_BBO: u32 = 50;
const PERPS_GENERAL: u32 = 30;
let lowest = [PIN_KLINES, PIN_TRADES, PIN_PORTFOLIO, PIN_BBO]
.into_iter()
.min()
.expect("four rows");
let mut table = WindowQuotaTable::new(PERPS_GENERAL, TEN_SECONDS);
table
.prefix("/v1/info/klines", None, PIN_KLINES, TEN_SECONDS)
.prefix("/v1/info/trades", None, PIN_TRADES, TEN_SECONDS)
.prefix("/v1/info/portfolio", None, PIN_PORTFOLIO, TEN_SECONDS)
.prefix("/v1/info/bbo", None, PIN_BBO, TEN_SECONDS)
.prefix("/v1/info", None, lowest, TEN_SECONDS);
table.build()
}