Skip to main content

finam_sdk/
lib.rs

1use tonic::{client::Grpc, service::interceptor::InterceptedService, transport::{Channel, ClientTlsConfig}};
2
3use crate::{auth::TokenInterceptor, stream::StartStream};
4
5pub const RETRY_DELAY: std::time::Duration = std::time::Duration::from_secs(5);
6pub const FINAM_ENDPOINT: &str = "https://api.finam.ru";
7
8pub mod proto;
9pub mod auth;
10pub mod stream;
11pub mod request;
12
13pub type StdError = Box<dyn std::error::Error + Send + Sync + 'static>;
14pub trait GrpcInner: tonic::client::GrpcService<
15    tonic::body::Body, 
16    Error: Into<StdError> + Send, 
17    ResponseBody: tonic::transport::Body<Data = prost::bytes::Bytes, Error: Into<StdError> + Send> + Send  + 'static,
18    Future: Send
19> {}
20
21impl <B, BE, E, S> GrpcInner for S where 
22    S: tonic::client::GrpcService<tonic::body::Body, Error = E, ResponseBody = B>, 
23    S::Future: Send,
24    E: Into<StdError> + Send, 
25    B: tonic::transport::Body<Data = prost::bytes::Bytes, Error = BE> + Send  + 'static,
26    BE: Into<StdError> + Send
27{}
28
29#[derive(Clone)]
30pub struct FinamApi {
31    token: std::sync::Arc<std::sync::Mutex<auth::Token>>,
32    grpc: Grpc<InterceptedService<Channel, auth::TokenInterceptor>>,
33}
34
35impl FinamApi {
36    pub async fn connect(secret: String) -> Result<Self, tonic::Status> {
37        let tls = ClientTlsConfig::new().with_native_roots();
38        let channel = Channel::from_static(FINAM_ENDPOINT).tls_config(tls).unwrap().connect_lazy();
39        let interceptor = TokenInterceptor::new(channel.clone(), secret).await?;
40        let token = interceptor.get_token();
41        let service = Grpc::new(InterceptedService::new(channel, interceptor));
42        Ok(Self{token, grpc: service})
43    }
44    pub fn token(&self) -> String {
45        self.token.lock().unwrap().clone().to_str().unwrap().to_string()
46    }
47    pub fn grpc(&self) -> Grpc<InterceptedService<Channel, auth::TokenInterceptor>> {
48        self.grpc.clone()
49    }
50}