xtb_api/
lib.rs

1#![allow(non_camel_case_types)]
2#![allow(non_snake_case)]
3
4pub mod models;
5
6use std::{
7    io::{Error, Read, Write},
8    net::TcpStream,
9};
10
11use models::ConnectionType;
12use native_tls::{TlsConnector, TlsStream};
13
14const HOST: &str = "xapi.xtb.com";
15const PORT_LIVE: &str = "5112";
16const PORT_DEMO: &str = "5124";
17
18pub struct Client {
19    main_connection: TlsStream<TcpStream>,
20    stream_session_id: Option<String>,
21    // stream_connection: Option<TlsStream<TcpStream>>, // Will be used for actual streaming connection
22}
23
24impl Client {
25    pub fn new(connection_type: ConnectionType) -> Client {
26        let connector = TlsConnector::new().unwrap();
27        let main_connection = Client::build_main_connection(&connection_type, &connector);
28
29        Client {
30            main_connection: main_connection,
31            stream_session_id: None,
32            // stream_connection: None,
33        }
34    }
35
36    pub fn login(&mut self, user_id: u64, password: String) -> Result<(), Error> {
37        let login_request = models::LoginRequest {
38            command: models::Command::login.to_string(),
39            arguments: models::LoginRequestArguments {
40                user_id: user_id,
41                password: password,
42            },
43        };
44
45        let request = serde_json::to_string(&login_request)?;
46
47        self.main_connection
48            .write_all(request.as_bytes())
49            .expect("write failed");
50
51        let mut buffer = [0; 4096];
52        self.main_connection.read(&mut buffer)?;
53
54        let data_string = String::from_utf8_lossy(&buffer);
55
56        let trimmed_data_string = &data_string.split("\n\n").next().unwrap();
57
58        let login_response: models::LoginResponse = serde_json::from_str(&trimmed_data_string)?;
59
60        self.stream_session_id = Some(login_response.stream_session_id);
61
62        Ok(())
63    }
64
65    pub fn balance(&mut self) -> Result<models::Response<models::Balance>, Error> {
66        let balance_request = models::Request {
67            command: models::Command::getMarginLevel.to_string(),
68        };
69
70        let request = serde_json::to_string(&balance_request)?;
71
72        self.main_connection
73            .write_all(request.as_bytes())
74            .expect("write failed");
75
76        let mut buffer = [0; 4096];
77        self.main_connection.read(&mut buffer)?;
78
79        let data_string = String::from_utf8_lossy(&buffer);
80
81        let trimmed_data_string = data_string.split("\n\n").next().unwrap();
82
83        let balance_response: models::Response<models::Balance> =
84            serde_json::from_str(&trimmed_data_string)?;
85
86        Ok(balance_response)
87    }
88
89    fn build_main_connection(
90        connection_type: &ConnectionType,
91        connector: &TlsConnector,
92    ) -> TlsStream<TcpStream> {
93        let addr = Client::build_addr(connection_type);
94        let stream = TcpStream::connect(addr).expect("Could not connect to the XTB API");
95
96        connector.connect(HOST, stream).unwrap()
97    }
98
99    fn build_addr(connection_type: &ConnectionType) -> String {
100        match connection_type {
101            ConnectionType::Live => format!("{}:{}", HOST, PORT_LIVE),
102            ConnectionType::Demo => format!("{}:{}", HOST, PORT_DEMO),
103        }
104    }
105}