use std::time::Duration;
pub const REST_API_ENDPOINT: &str = "https://api.binance.com";
pub const WS_ENDPOINT: &str = "wss://stream.binance.com:9443";
pub const TESTNET_REST_API_ENDPOINT: &str = "https://testnet.binance.vision";
pub const TESTNET_WS_ENDPOINT: &str = "wss://testnet.binance.vision";
pub const BINANCE_US_REST_API_ENDPOINT: &str = "https://api.binance.us";
pub const BINANCE_US_WS_ENDPOINT: &str = "wss://stream.binance.us:9443";
pub const DEFAULT_RECV_WINDOW: u64 = 5000;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Config {
pub rest_api_endpoint: String,
pub ws_endpoint: String,
pub recv_window: u64,
pub timeout: Option<Duration>,
pub binance_us: bool,
}
impl Config {
pub fn builder() -> ConfigBuilder {
ConfigBuilder::default()
}
pub fn testnet() -> Self {
Config {
rest_api_endpoint: TESTNET_REST_API_ENDPOINT.to_string(),
ws_endpoint: TESTNET_WS_ENDPOINT.to_string(),
recv_window: DEFAULT_RECV_WINDOW,
timeout: None,
binance_us: false,
}
}
pub fn binance_us() -> Self {
Config {
rest_api_endpoint: BINANCE_US_REST_API_ENDPOINT.to_string(),
ws_endpoint: BINANCE_US_WS_ENDPOINT.to_string(),
recv_window: DEFAULT_RECV_WINDOW,
timeout: None,
binance_us: true,
}
}
}
impl Default for Config {
fn default() -> Self {
Config {
rest_api_endpoint: REST_API_ENDPOINT.to_string(),
ws_endpoint: WS_ENDPOINT.to_string(),
recv_window: DEFAULT_RECV_WINDOW,
timeout: None,
binance_us: false,
}
}
}
#[derive(Clone, Debug, Default)]
pub struct ConfigBuilder {
rest_api_endpoint: Option<String>,
ws_endpoint: Option<String>,
recv_window: Option<u64>,
timeout: Option<Duration>,
binance_us: bool,
}
impl ConfigBuilder {
pub fn rest_api_endpoint(mut self, endpoint: impl Into<String>) -> Self {
self.rest_api_endpoint = Some(endpoint.into());
self
}
pub fn ws_endpoint(mut self, endpoint: impl Into<String>) -> Self {
self.ws_endpoint = Some(endpoint.into());
self
}
pub fn recv_window(mut self, recv_window: u64) -> Self {
self.recv_window = Some(recv_window);
self
}
pub fn timeout(mut self, timeout: Duration) -> Self {
self.timeout = Some(timeout);
self
}
pub fn timeout_secs(self, secs: u64) -> Self {
self.timeout(Duration::from_secs(secs))
}
pub fn binance_us(mut self, is_binance_us: bool) -> Self {
self.binance_us = is_binance_us;
self
}
pub fn build(self) -> Config {
let (default_rest, default_ws) = if self.binance_us {
(BINANCE_US_REST_API_ENDPOINT, BINANCE_US_WS_ENDPOINT)
} else {
(REST_API_ENDPOINT, WS_ENDPOINT)
};
Config {
rest_api_endpoint: self
.rest_api_endpoint
.unwrap_or_else(|| default_rest.to_string()),
ws_endpoint: self.ws_endpoint.unwrap_or_else(|| default_ws.to_string()),
recv_window: self.recv_window.unwrap_or(DEFAULT_RECV_WINDOW),
timeout: self.timeout,
binance_us: self.binance_us,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_config() {
let config = Config::default();
assert_eq!(config.rest_api_endpoint, REST_API_ENDPOINT);
assert_eq!(config.ws_endpoint, WS_ENDPOINT);
assert_eq!(config.recv_window, DEFAULT_RECV_WINDOW);
assert!(config.timeout.is_none());
assert!(!config.binance_us);
}
#[test]
fn test_testnet_config() {
let config = Config::testnet();
assert_eq!(config.rest_api_endpoint, TESTNET_REST_API_ENDPOINT);
assert_eq!(config.ws_endpoint, TESTNET_WS_ENDPOINT);
assert_eq!(config.recv_window, DEFAULT_RECV_WINDOW);
assert!(!config.binance_us);
}
#[test]
fn test_binance_us_config() {
let config = Config::binance_us();
assert_eq!(config.rest_api_endpoint, BINANCE_US_REST_API_ENDPOINT);
assert_eq!(config.ws_endpoint, BINANCE_US_WS_ENDPOINT);
assert!(config.binance_us);
}
#[test]
fn test_config_builder() {
let config = Config::builder()
.rest_api_endpoint("https://custom.api.com")
.ws_endpoint("wss://custom.ws.com")
.recv_window(3000)
.timeout_secs(30)
.build();
assert_eq!(config.rest_api_endpoint, "https://custom.api.com");
assert_eq!(config.ws_endpoint, "wss://custom.ws.com");
assert_eq!(config.recv_window, 3000);
assert_eq!(config.timeout, Some(Duration::from_secs(30)));
}
#[test]
fn test_config_builder_binance_us_defaults() {
let config = Config::builder().binance_us(true).build();
assert_eq!(config.rest_api_endpoint, BINANCE_US_REST_API_ENDPOINT);
assert_eq!(config.ws_endpoint, BINANCE_US_WS_ENDPOINT);
assert!(config.binance_us);
}
}