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}