lit_sdk/
lib.rs

1//!
2//! The Rust Lit-Node SDK
3//!
4
5#[macro_use]
6mod macros;
7pub mod admin;
8#[cfg(feature = "cait-sith")]
9pub mod cait_sith;
10mod common;
11pub mod encryption;
12mod error;
13mod execute_function;
14mod handshake;
15mod payload;
16mod pkp_claim;
17mod pkp_sign;
18mod session_key;
19mod sev_snp;
20pub mod signature;
21
22pub use common::*;
23pub use encryption::{EncryptionSignRequest, EncryptionSignRequestBuilder, EncryptionSignResponse};
24pub use error::*;
25pub use execute_function::*;
26pub use handshake::*;
27pub use payload::*;
28pub use pkp_claim::*;
29pub use pkp_sign::*;
30pub use session_key::*;
31pub use sev_snp::*;
32
33pub use lit_node_core;
34pub use sev;
35pub use uuid;
36
37use serde::Serialize;
38use std::{collections::HashMap, sync::OnceLock, time::Duration};
39
40static HTTP_CLIENT: OnceLock<reqwest::Client> = OnceLock::new();
41
42fn get_http_client() -> &'static reqwest::Client {
43    HTTP_CLIENT.get_or_init(|| {
44        reqwest::Client::builder()
45            .pool_idle_timeout(Some(Duration::from_secs(10)))
46            .tls_sni(false)
47            .build()
48            .expect("Failed to build HTTP client")
49    })
50}
51
52/// Compute the ipfs hash of a string
53pub fn compute_ipfs_hash(code: &str) -> String {
54    ipfs_hasher::IpfsHasher::default().compute(code.as_bytes())
55}
56
57async fn request<B>(
58    url_prefix: UrlPrefix,
59    socket_address: &str,
60    api_path: &str,
61    request_id: &str,
62    custom_headers: &HashMap<String, String>,
63    body: B,
64) -> SdkResult<reqwest::Response>
65where
66    B: Serialize,
67{
68    let client = get_http_client();
69    let mut request_builder = client
70        .post(format!("{}://{}/{}", url_prefix, socket_address, api_path))
71        .header("Content-Type", "application/json")
72        .header("Accept", "application/json");
73    if !request_id.is_empty() {
74        request_builder = request_builder.header("X-Request-Id", request_id);
75    }
76    for (custom_header, value) in custom_headers {
77        request_builder = request_builder.header(custom_header, value);
78    }
79    let response_output = request_builder
80        .body(serde_json::to_string(&body)?)
81        .send()
82        .await?;
83    Ok(response_output)
84}
85
86fn extract_headers(response_output: &reqwest::Response) -> SdkResult<HashMap<String, String>> {
87    let response_headers = response_output.headers();
88    let mut out_headers = HashMap::with_capacity(response_headers.len());
89    for (k, v) in response_headers {
90        out_headers.insert(k.to_string(), v.to_str()?.to_string());
91    }
92    Ok(out_headers)
93}
94
95#[cfg(test)]
96mod tests {
97    use super::*;
98
99    #[test]
100    fn url_prefix_parse() {
101        assert_eq!(UrlPrefix::Http, "http".parse::<UrlPrefix>().unwrap());
102        assert_eq!(UrlPrefix::Http, "HTTP".parse::<UrlPrefix>().unwrap());
103        assert_eq!(UrlPrefix::Https, "https".parse::<UrlPrefix>().unwrap());
104        assert_eq!(UrlPrefix::Https, "HTTPS".parse::<UrlPrefix>().unwrap());
105        assert!("ftp".parse::<UrlPrefix>().is_err());
106    }
107
108    #[test]
109    fn url_prefix_to_string() {
110        assert_eq!(UrlPrefix::Http.to_string(), "http");
111        assert_eq!(UrlPrefix::Https.to_string(), "https");
112    }
113
114    #[test]
115    fn url_prefix_default() {
116        assert_eq!(UrlPrefix::Https, UrlPrefix::default());
117    }
118}