koios-sdk 0.1.1

A Rust SDK for the Koios Cardano API
Documentation
use crate::{
    error::Result,
    models::epoch::{EpochBlockProtocol, EpochInfo, EpochParams},
    types::{EpochNo, IncludeNextEpoch},
    Client,
};
use urlencoding::encode;

impl Client {
    /// Get the epoch information, all epochs if no epoch specified
    ///
    /// # Arguments
    ///
    /// * `epoch_no` - Optional epoch number to query
    /// * `include_next_epoch` - Whether to include information about nearing but not yet started epoch
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use koios_sdk::{Client, types::{EpochNo, IncludeNextEpoch}};
    ///
    /// #[tokio::main]
    /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
    ///     let client = Client::new()?;
    ///     
    ///     // Get all epochs
    ///     let all_epochs = client.get_epoch_info(None, None).await?;
    ///     
    ///     // Get specific epoch with next epoch info
    ///     let epoch = client.get_epoch_info(
    ///         Some(EpochNo::new("320")),
    ///         Some(IncludeNextEpoch::new(true))
    ///     ).await?;
    ///     
    ///     Ok(())
    /// }
    /// ```
    pub async fn get_epoch_info(
        &self,
        epoch_no: Option<EpochNo>,
        include_next_epoch: Option<IncludeNextEpoch>,
    ) -> Result<Vec<EpochInfo>> {
        use urlencoding::encode;

        let mut query_params = vec![];

        if let Some(epoch) = epoch_no {
            query_params.push(("_epoch_no", epoch.0));
        }

        if let Some(include_next) = include_next_epoch {
            query_params.push(("_include_next_epoch", include_next.0.to_string()));
        }

        let query_string = if !query_params.is_empty() {
            let encoded_params: Vec<String> = query_params
                .into_iter()
                .map(|(k, v)| format!("{}={}", encode(k), encode(&v)))
                .collect();
            format!("?{}", encoded_params.join("&"))
        } else {
            String::new()
        };

        self.get(&format!("/epoch_info{}", query_string)).await
    }

    /// Get the protocol parameters for specific epoch, returns information about all epochs if no epoch specified
    ///
    /// # Arguments
    ///
    /// * `epoch_no` - Optional epoch number to query
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use koios_sdk::{Client, types::EpochNo};
    ///
    /// #[tokio::main]
    /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
    ///     let client = Client::new()?;
    ///     
    ///     // Get all epochs' parameters
    ///     let all_params = client.get_epoch_params(None).await?;
    ///     
    ///     // Get specific epoch parameters
    ///     let params = client.get_epoch_params(Some(EpochNo::new("320"))).await?;
    ///     
    ///     Ok(())
    /// }
    /// ```
    pub async fn get_epoch_params(&self, epoch_no: Option<EpochNo>) -> Result<Vec<EpochParams>> {
        let endpoint = match epoch_no {
            Some(epoch) => format!("/epoch_params?_epoch_no={}", encode(epoch.value())),
            None => "/epoch_params".to_string(),
        };
        self.get(&endpoint).await
    }

    /// Get block protocol versions for specific epoch, returns information about all epochs if no epoch specified
    ///
    /// # Arguments
    ///
    /// * `epoch_no` - Optional epoch number to query
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use koios_sdk::{Client, types::EpochNo};
    ///
    /// #[tokio::main]
    /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
    ///     let client = Client::new()?;
    ///     
    ///     // Get all epochs' block protocols
    ///     let all_protocols = client.get_epoch_block_protocols(None).await?;
    ///     
    ///     // Get specific epoch block protocols
    ///     let protocols = client.get_epoch_block_protocols(Some(EpochNo::new("320"))).await?;
    ///     
    ///     Ok(())
    /// }
    /// ```
    pub async fn get_epoch_block_protocols(
        &self,
        epoch_no: Option<EpochNo>,
    ) -> Result<Vec<EpochBlockProtocol>> {
        let endpoint = match epoch_no {
            Some(epoch) => format!("/epoch_block_protocols?_epoch_no={}", encode(epoch.value())),
            None => "/epoch_block_protocols".to_string(),
        };
        self.get(&endpoint).await
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use tokio;

    #[tokio::test]
    async fn test_get_epoch_info() {
        let client = Client::new().unwrap();

        // Test without parameters
        let result = client.get_epoch_info(None, None).await;
        assert!(result.is_ok());

        // Test with epoch number
        let result = client.get_epoch_info(Some(EpochNo::new("320")), None).await;
        assert!(result.is_ok());

        // Test with include_next_epoch
        let result = client
            .get_epoch_info(None, Some(IncludeNextEpoch::new(true)))
            .await;
        assert!(result.is_ok());

        // Test with both parameters
        let result = client
            .get_epoch_info(Some(EpochNo::new("320")), Some(IncludeNextEpoch::new(true)))
            .await;
        assert!(result.is_ok());
    }

    #[tokio::test]
    async fn test_get_epoch_params() {
        let client = Client::new().unwrap();

        // Test without parameters
        let result = client.get_epoch_params(None).await;
        assert!(result.is_ok());

        // Test with epoch number
        let result = client.get_epoch_params(Some(EpochNo::new("320"))).await;
        assert!(result.is_ok());
    }

    #[tokio::test]
    async fn test_get_epoch_block_protocols() {
        let client = Client::new().unwrap();

        // Test without parameters
        let result = client.get_epoch_block_protocols(None).await;
        assert!(result.is_ok());

        // Test with epoch number
        let result = client
            .get_epoch_block_protocols(Some(EpochNo::new("320")))
            .await;
        assert!(result.is_ok());
    }
}