use url::Url;
use crate::auth::AuthService;
use crate::config::{
FyersConfig, SecretString, default_api_base_url, default_api_v2_base_url,
default_data_base_url, default_data_socket_url, default_order_socket_url,
default_symbols_base_url, default_tbt_socket_url, default_timeout,
};
use crate::error::{FyersError, Result};
use crate::rest::alerts::AlertsService;
use crate::rest::edis::EdisService;
use crate::rest::funds::FundsService;
use crate::rest::gtt::GttService;
use crate::rest::holdings::HoldingsService;
use crate::rest::market_data::MarketDataService;
use crate::rest::orders::OrdersService;
use crate::rest::positions::PositionsService;
use crate::rest::profile::ProfileService;
use crate::rest::reports::ReportsService;
use crate::rest::smart_orders::SmartOrdersService;
use crate::rest::trades::TradesService;
use crate::ws::{DataSocketService, OrderSocketService, TbtSocketService};
#[derive(Clone, Debug)]
pub struct FyersClient {
config: FyersConfig,
http: reqwest::Client,
}
impl FyersClient {
pub fn builder() -> FyersClientBuilder {
FyersClientBuilder::default()
}
pub fn from_parts(config: FyersConfig, http: reqwest::Client) -> Self {
Self { config, http }
}
pub fn config(&self) -> &FyersConfig {
&self.config
}
pub fn http(&self) -> &reqwest::Client {
&self.http
}
pub fn auth(&self) -> AuthService<'_> {
AuthService::new(self)
}
pub fn profile(&self) -> ProfileService<'_> {
ProfileService::new(self)
}
pub fn funds(&self) -> FundsService<'_> {
FundsService::new(self)
}
pub fn holdings(&self) -> HoldingsService<'_> {
HoldingsService::new(self)
}
pub fn orders(&self) -> OrdersService<'_> {
OrdersService::new(self)
}
pub fn trades(&self) -> TradesService<'_> {
TradesService::new(self)
}
pub fn positions(&self) -> PositionsService<'_> {
PositionsService::new(self)
}
pub fn gtt(&self) -> GttService<'_> {
GttService::new(self)
}
pub fn smart_orders(&self) -> SmartOrdersService<'_> {
SmartOrdersService::new(self)
}
pub fn market_data(&self) -> MarketDataService<'_> {
MarketDataService::new(self)
}
pub fn alerts(&self) -> AlertsService<'_> {
AlertsService::new(self)
}
pub fn reports(&self) -> ReportsService<'_> {
ReportsService::new(self)
}
pub fn edis(&self) -> EdisService<'_> {
EdisService::new(self)
}
pub fn data_socket(&self) -> DataSocketService<'_> {
DataSocketService::new(self)
}
pub fn order_socket(&self) -> OrderSocketService<'_> {
OrderSocketService::new(self)
}
pub fn tbt_socket(&self) -> TbtSocketService<'_> {
TbtSocketService::new(self)
}
}
#[derive(Debug, Default)]
pub struct FyersClientBuilder {
client_id: Option<String>,
secret_key: Option<String>,
redirect_uri: Option<Url>,
access_token: Option<String>,
api_base_url: Option<Url>,
api_v2_base_url: Option<Url>,
data_base_url: Option<Url>,
symbols_base_url: Option<Url>,
data_socket_url: Option<Url>,
order_socket_url: Option<Url>,
tbt_socket_url: Option<Url>,
http: Option<reqwest::Client>,
timeout: Option<std::time::Duration>,
}
impl FyersClientBuilder {
pub fn client_id(mut self, client_id: impl Into<String>) -> Self {
self.client_id = Some(client_id.into());
self
}
pub fn secret_key(mut self, secret_key: impl Into<String>) -> Self {
self.secret_key = Some(secret_key.into());
self
}
pub fn redirect_uri(mut self, redirect_uri: Url) -> Self {
self.redirect_uri = Some(redirect_uri);
self
}
pub fn redirect_uri_str(mut self, redirect_uri: impl AsRef<str>) -> Result<Self> {
self.redirect_uri = Some(Url::parse(redirect_uri.as_ref())?);
Ok(self)
}
pub fn access_token(mut self, access_token: impl Into<String>) -> Self {
self.access_token = Some(access_token.into());
self
}
pub fn api_base_url(mut self, api_base_url: Url) -> Self {
self.api_base_url = Some(api_base_url);
self
}
pub fn api_base_url_str(mut self, api_base_url: impl AsRef<str>) -> Result<Self> {
self.api_base_url = Some(Url::parse(api_base_url.as_ref())?);
Ok(self)
}
pub fn api_v2_base_url(mut self, api_v2_base_url: Url) -> Self {
self.api_v2_base_url = Some(api_v2_base_url);
self
}
pub fn api_v2_base_url_str(mut self, api_v2_base_url: impl AsRef<str>) -> Result<Self> {
self.api_v2_base_url = Some(Url::parse(api_v2_base_url.as_ref())?);
Ok(self)
}
pub fn data_base_url(mut self, data_base_url: Url) -> Self {
self.data_base_url = Some(data_base_url);
self
}
pub fn data_base_url_str(mut self, data_base_url: impl AsRef<str>) -> Result<Self> {
self.data_base_url = Some(Url::parse(data_base_url.as_ref())?);
Ok(self)
}
pub fn symbols_base_url(mut self, symbols_base_url: Url) -> Self {
self.symbols_base_url = Some(symbols_base_url);
self
}
pub fn symbols_base_url_str(mut self, symbols_base_url: impl AsRef<str>) -> Result<Self> {
self.symbols_base_url = Some(Url::parse(symbols_base_url.as_ref())?);
Ok(self)
}
pub fn data_socket_url(mut self, data_socket_url: Url) -> Self {
self.data_socket_url = Some(data_socket_url);
self
}
pub fn data_socket_url_str(mut self, data_socket_url: impl AsRef<str>) -> Result<Self> {
self.data_socket_url = Some(Url::parse(data_socket_url.as_ref())?);
Ok(self)
}
pub fn order_socket_url(mut self, order_socket_url: Url) -> Self {
self.order_socket_url = Some(order_socket_url);
self
}
pub fn order_socket_url_str(mut self, order_socket_url: impl AsRef<str>) -> Result<Self> {
self.order_socket_url = Some(Url::parse(order_socket_url.as_ref())?);
Ok(self)
}
pub fn tbt_socket_url(mut self, tbt_socket_url: Url) -> Self {
self.tbt_socket_url = Some(tbt_socket_url);
self
}
pub fn tbt_socket_url_str(mut self, tbt_socket_url: impl AsRef<str>) -> Result<Self> {
self.tbt_socket_url = Some(Url::parse(tbt_socket_url.as_ref())?);
Ok(self)
}
pub fn http_client(mut self, http: reqwest::Client) -> Self {
self.http = Some(http);
self
}
pub fn timeout(mut self, timeout: std::time::Duration) -> Self {
self.timeout = Some(timeout);
self
}
pub fn build(self) -> Result<FyersClient> {
let client_id = self
.client_id
.ok_or(FyersError::MissingConfig { field: "client_id" })?;
let timeout = self.timeout.unwrap_or_else(default_timeout);
let config = FyersConfig::new(
client_id,
self.secret_key.map(SecretString::new),
self.redirect_uri,
self.access_token.map(SecretString::new),
self.api_base_url.unwrap_or_else(default_api_base_url),
self.api_v2_base_url.unwrap_or_else(default_api_v2_base_url),
self.data_base_url.unwrap_or_else(default_data_base_url),
self.symbols_base_url
.unwrap_or_else(default_symbols_base_url),
self.data_socket_url.unwrap_or_else(default_data_socket_url),
self.order_socket_url
.unwrap_or_else(default_order_socket_url),
self.tbt_socket_url.unwrap_or_else(default_tbt_socket_url),
timeout,
);
let http = match self.http {
Some(http) => http,
None => reqwest::Client::builder().timeout(timeout).build()?,
};
Ok(FyersClient::from_parts(config, http))
}
}