110 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			110 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
// SPDX-License-Identifier: Apache-2.0
 | 
						|
 | 
						|
use crate::config::Config;
 | 
						|
use tonic::{
 | 
						|
    metadata::{errors::InvalidMetadataValue, AsciiMetadataValue},
 | 
						|
    Request,
 | 
						|
};
 | 
						|
 | 
						|
#[derive(thiserror::Error, Debug)]
 | 
						|
pub enum Error {
 | 
						|
    #[error(transparent)]
 | 
						|
    ConfigError(#[from] crate::config::Error),
 | 
						|
    #[error(transparent)]
 | 
						|
    InternalError(#[from] InvalidMetadataValue),
 | 
						|
}
 | 
						|
 | 
						|
pub fn block_on<F>(future: F) -> F::Output
 | 
						|
where
 | 
						|
    F: std::future::Future,
 | 
						|
{
 | 
						|
    tokio::runtime::Runtime::new().unwrap().block_on(future)
 | 
						|
}
 | 
						|
 | 
						|
pub fn sign_request<T: std::fmt::Debug>(req: T) -> Result<Request<T>, Error> {
 | 
						|
    let pubkey = Config::get_detee_wallet()?;
 | 
						|
    let timestamp = chrono::Utc::now().to_rfc3339();
 | 
						|
    let signature = Config::try_sign_message(&format!("{timestamp}{req:?}"))?;
 | 
						|
    let timestamp: AsciiMetadataValue = timestamp.parse()?;
 | 
						|
    let pubkey: AsciiMetadataValue = pubkey.parse()?;
 | 
						|
    let signature: AsciiMetadataValue = signature.parse()?;
 | 
						|
    let mut req = Request::new(req);
 | 
						|
    req.metadata_mut().insert("timestamp", timestamp);
 | 
						|
    req.metadata_mut().insert("pubkey", pubkey);
 | 
						|
    req.metadata_mut().insert("request-signature", signature);
 | 
						|
    Ok(req)
 | 
						|
}
 | 
						|
 | 
						|
pub fn shorten_string(my_string: &String) -> String {
 | 
						|
    if my_string.len() <= 8 {
 | 
						|
        my_string.to_string()
 | 
						|
    } else {
 | 
						|
        let first_part = &my_string[..8];
 | 
						|
        // let last_part = &my_string[my_string.len() - 4..];
 | 
						|
        format!("{}", first_part)
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
pub fn display_mib_or_gib(value: &u64) -> String {
 | 
						|
    if *value >= 1024 {
 | 
						|
        if *value < 102400 {
 | 
						|
            let value = (value / 102) as f64;
 | 
						|
            format!("{}G", value / 10_f64)
 | 
						|
        } else {
 | 
						|
            format!("{}G", value / 1024)
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        format!("{}M", value)
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
#[macro_export]
 | 
						|
macro_rules! call_with_follow_redirect {
 | 
						|
    (
 | 
						|
        $client:expr,
 | 
						|
        $req_data:expr,
 | 
						|
        $method:ident
 | 
						|
    ) => {
 | 
						|
        async {
 | 
						|
            let mut client = $client;
 | 
						|
 | 
						|
            for attempt in 0..crate::constants::MAX_REDIRECTS {
 | 
						|
                log::debug!(
 | 
						|
                    "Attempt #{}: Calling method '{}'...",
 | 
						|
                    attempt + 1,
 | 
						|
                    stringify!($method)
 | 
						|
                );
 | 
						|
 | 
						|
                let req_data_clone = $req_data.clone();
 | 
						|
                let signed_req = crate::utils::sign_request(req_data_clone)?;
 | 
						|
 | 
						|
                match client.$method(signed_req).await {
 | 
						|
                    Ok(resp) => return Ok(resp),
 | 
						|
 | 
						|
                    Err(status)
 | 
						|
                        if status.code() == tonic::Code::Unavailable
 | 
						|
                            && status.message() == "moved" =>
 | 
						|
                    {
 | 
						|
                        let redirect_url = status
 | 
						|
                            .metadata()
 | 
						|
                            .get("location")
 | 
						|
                            .and_then(|v| v.to_str().ok())
 | 
						|
                            .ok_or_else(|| {
 | 
						|
                                Error::RedirectError(
 | 
						|
                                    "Server indicated a move but provided no location".into(),
 | 
						|
                                )
 | 
						|
                            })?;
 | 
						|
 | 
						|
                        log::info!("Server moved. Redirecting to {}...", redirect_url);
 | 
						|
 | 
						|
                        client = client_from_endpoint(format!("https://{}", redirect_url)).await?;
 | 
						|
                        continue;
 | 
						|
                    }
 | 
						|
                    Err(e) => return Err(Error::ResponseStatus(e)),
 | 
						|
                }
 | 
						|
            }
 | 
						|
            Err(Error::MaxRedirectsExceeded(crate::constants::MAX_REDIRECTS.to_string()))
 | 
						|
        }
 | 
						|
    };
 | 
						|
}
 |