longportwhale/
config.rs

1pub(crate) use http::{header, HeaderValue, Request};
2use longportwhale_httpcli::{HttpClient, HttpClientConfig};
3use num_enum::IntoPrimitive;
4use tokio_tungstenite::tungstenite::client::IntoClientRequest;
5
6use crate::error::Result;
7
8const TRADE_WS_URL: &str = "wss://openapi-trade.longportapp.com";
9
10/// Language identifier
11#[derive(Debug, Copy, Clone, PartialEq, Eq, IntoPrimitive)]
12#[allow(non_camel_case_types)]
13#[repr(i32)]
14pub enum Language {
15    /// zh-CN
16    ZH_CN = 0,
17    /// zh-HK
18    ZH_HK = 2,
19    /// en
20    EN = 1,
21}
22
23impl Language {
24    pub(crate) fn as_str(&self) -> &'static str {
25        match self {
26            Language::ZH_CN => "zh-CN",
27            Language::ZH_HK => "zh-HK",
28            Language::EN => "en",
29        }
30    }
31}
32
33/// Configuration options for LongPort sdk
34#[derive(Debug, Clone)]
35pub struct Config {
36    pub(crate) http_cli_config: HttpClientConfig,
37    pub(crate) trade_ws_url: String,
38    pub(crate) language: Language,
39}
40
41impl Config {
42    /// Create a new `Config`
43    pub fn new(
44        app_key: impl Into<String>,
45        app_secret: impl Into<String>,
46        access_token: impl Into<String>,
47    ) -> Self {
48        Self {
49            http_cli_config: HttpClientConfig::new(app_key, app_secret, access_token),
50            trade_ws_url: TRADE_WS_URL.to_string(),
51            language: Language::EN,
52        }
53    }
54
55    /// Create a new `Config` from the given environment variables
56    ///
57    /// It first gets the environment variables from the `.env` file in the
58    /// current directory.
59    ///
60    /// # Variables
61    ///
62    /// - `LONGPORT_APP_KEY` - App key
63    /// - `LONGPORT_APP_SECRET` - App secret
64    /// - `LONGPORT_ACCESS_TOKEN` - Access token
65    /// - `LONGPORT_HTTP_URL` - HTTP endpoint url (Default: `https://openapi.longportapp.com`)
66    /// - `LONGPORT_TRADE_WS_URL` - Trade websocket endpoint url (Default:
67    ///   `wss://openapi-trade.longportapp.com`)
68    pub fn from_env() -> Result<Self> {
69        let _ = dotenv::dotenv();
70
71        let http_cli_config = HttpClientConfig::from_env()?;
72        let trade_ws_url =
73            std::env::var("LONGPORT_TRADE_WS_URL").unwrap_or_else(|_| TRADE_WS_URL.to_string());
74
75        Ok(Config {
76            http_cli_config,
77            trade_ws_url,
78            language: Language::EN,
79        })
80    }
81
82    /// Specifies the url of the OpenAPI server.
83    ///
84    /// Default: `https://openapi.longportapp.com`
85    ///
86    /// NOTE: Usually you don't need to change it.
87    #[must_use]
88    pub fn http_url(mut self, url: impl Into<String>) -> Self {
89        self.http_cli_config = self.http_cli_config.http_url(url);
90        self
91    }
92
93    /// Specifies the url of the OpenAPI trade websocket server.
94    ///
95    /// Default: `wss://openapi-trade.longportapp.com`
96    ///
97    /// NOTE: Usually you don't need to change it.
98    #[must_use]
99    pub fn trade_ws_url(self, url: impl Into<String>) -> Self {
100        Self {
101            trade_ws_url: url.into(),
102            ..self
103        }
104    }
105
106    /// Specifies the language
107    ///
108    /// Default: `Language::EN`
109    pub fn language(self, language: Language) -> Self {
110        Self { language, ..self }
111    }
112
113    /// Create http client use the http client config
114    pub fn create_http_client(&self) -> HttpClient {
115        HttpClient::new(self.http_cli_config.clone())
116            .header(header::ACCEPT_LANGUAGE, self.language.as_str())
117    }
118
119    fn create_ws_request(&self, url: &str) -> tokio_tungstenite::tungstenite::Result<Request<()>> {
120        let mut request = url.into_client_request()?;
121        request.headers_mut().append(
122            header::ACCEPT_LANGUAGE,
123            HeaderValue::from_str(self.language.as_str()).unwrap(),
124        );
125        Ok(request)
126    }
127
128    #[inline]
129    pub(crate) fn create_trade_ws_request(
130        &self,
131    ) -> tokio_tungstenite::tungstenite::Result<Request<()>> {
132        self.create_ws_request(&self.trade_ws_url)
133    }
134}