koios-sdk 0.1.1

A Rust SDK for the Koios Cardano API
Documentation
use crate::{
    error::Result,
    models::{
        requests::ScriptHashesRequest,
        script::{ScriptInfo, ScriptList, ScriptRedeemer},
        UtxoInfo,
    },
    types::{Extended, ScriptHash},
    Client,
};

impl Client {
    /// Get list of script information for given script hashes
    ///
    /// # Arguments
    ///
    /// * `script_hashes` - List of script hashes to query
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use koios_sdk::Client;
    ///
    /// #[tokio::main]
    /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
    ///     let client = Client::new()?;
    ///     let script_hashes = vec![
    ///         "67f33146617a5e61936081db3b2117cbf59bd2123748f58ac9678656".to_string()
    ///     ];
    ///     let info = client.get_script_info(&script_hashes).await?;
    ///     println!("Script info: {:?}", info);
    ///     Ok(())
    /// }
    /// ```
    pub async fn get_script_info(&self, script_hashes: &[String]) -> Result<Vec<ScriptInfo>> {
        let request = ScriptHashesRequest::new(script_hashes.to_vec());
        self.post("/script_info", &request).await
    }

    /// Get list of all existing native script hashes along with their creation transaction hashes
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use koios_sdk::Client;
    ///
    /// #[tokio::main]
    /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
    ///     let client = Client::new()?;
    ///     let scripts = client.get_native_script_list().await?;
    ///     println!("Native scripts: {:?}", scripts);
    ///     Ok(())
    /// }
    /// ```
    pub async fn get_native_script_list(&self) -> Result<Vec<ScriptList>> {
        self.get("/native_script_list").await
    }

    /// Get list of all existing Plutus script hashes along with their creation transaction hashes
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use koios_sdk::Client;
    ///
    /// #[tokio::main]
    /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
    ///     let client = Client::new()?;
    ///     let scripts = client.get_plutus_script_list().await?;
    ///     println!("Plutus scripts: {:?}", scripts);
    ///     Ok(())
    /// }
    /// ```
    pub async fn get_plutus_script_list(&self) -> Result<Vec<ScriptList>> {
        self.get("/plutus_script_list").await
    }

    /// Get list of all redeemers for a given script hash
    ///
    /// # Arguments
    ///
    /// * `script_hash` - Script hash to query
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use koios_sdk::Client;
    /// use koios_sdk::types::ScriptHash;
    ///
    /// #[tokio::main]
    /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
    ///     let client = Client::new()?;
    ///     let script_hash = ScriptHash::new(
    ///         "67f33146617a5e61936081db3b2117cbf59bd2123748f58ac9678656"
    ///     );
    ///     let redeemers = client.get_script_redeemers(&script_hash).await?;
    ///     println!("Script redeemers: {:?}", redeemers);
    ///     Ok(())
    /// }
    /// ```
    pub async fn get_script_redeemers(
        &self,
        script_hash: &ScriptHash,
    ) -> Result<Vec<ScriptRedeemer>> {
        self.get(&format!(
            "/script_redeemers?_script_hash={}",
            script_hash.value()
        ))
        .await
    }

    /// Get list of all UTXOs for a given script hash
    ///
    /// # Arguments
    ///
    /// * `script_hash` - Script hash to query
    /// * `extended` - Optional flag to include extended information
    ///
    /// # Examples
    ///
    /// ```no_run
    /// use koios_sdk::Client;
    /// use koios_sdk::types::{ScriptHash, Extended};
    ///
    /// #[tokio::main]
    /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
    ///     let client = Client::new()?;
    ///     let script_hash = ScriptHash::new(
    ///         "67f33146617a5e61936081db3b2117cbf59bd2123748f58ac9678656"
    ///     );
    ///     let utxos = client.get_script_utxos(&script_hash, Some(Extended::new(true))).await?;
    ///     println!("Script UTXOs: {:?}", utxos);
    ///     Ok(())
    /// }
    /// ```
    pub async fn get_script_utxos(
        &self,
        script_hash: &ScriptHash,
        extended: Option<Extended>,
    ) -> Result<Vec<UtxoInfo>> {
        let mut endpoint = format!("/script_utxos?_script_hash={}", script_hash.value());

        if let Some(ext) = extended {
            endpoint.push_str(&format!("&_extended={}", ext.value()));
        }

        self.get(&endpoint).await
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use serde_json::json;
    use wiremock::matchers::{method, path, query_param};
    use wiremock::{Mock, MockServer, ResponseTemplate};

    #[tokio::test]
    async fn test_get_plutus_script_list() {
        let mock_server = MockServer::start().await;
        let client = Client::builder()
            .base_url(mock_server.uri())
            .build()
            .unwrap();

        let mock_response = json!([{
            "script_hash": "67f33146617a5e61936081db3b2117cbf59bd2123748f58ac9678656",
            "creation_tx_hash": "6ed09ba58a56c6e946668038ba4d3cef8eb97a20cbf76c5970e1402e8a8d6541",
            "type": "plutusv1",
            "size": 42
        }]);

        Mock::given(method("GET"))
            .and(path("/plutus_script_list"))
            .respond_with(ResponseTemplate::new(200).set_body_json(&mock_response))
            .mount(&mock_server)
            .await;

        let response = client.get_plutus_script_list().await.unwrap();
        assert_eq!(response.len(), 1);
        assert_eq!(
            response[0].script_hash,
            "67f33146617a5e61936081db3b2117cbf59bd2123748f58ac9678656"
        );
    }

    #[tokio::test]
    async fn test_get_script_redeemers() {
        let mock_server = MockServer::start().await;
        let client = Client::builder()
            .base_url(mock_server.uri())
            .build()
            .unwrap();

        let script_hash = "67f33146617a5e61936081db3b2117cbf59bd2123748f58ac9678656";
        let mock_response = json!([{
            "script_hash": script_hash,
            "redeemers": [{
                "tx_hash": "6ed09ba58a56c6e946668038ba4d3cef8eb97a20cbf76c5970e1402e8a8d6541",
                "tx_index": 0,
                "unit_mem": 1000,
                "unit_steps": 500,
                "fee": "500000",
                "purpose": "spend",
                "datum_hash": "ab01cd23",
                "datum_value": null
            }]
        }]);

        Mock::given(method("GET"))
            .and(path("/script_redeemers"))
            .and(query_param("_script_hash", script_hash))
            .respond_with(ResponseTemplate::new(200).set_body_json(&mock_response))
            .mount(&mock_server)
            .await;

        let response = client
            .get_script_redeemers(&ScriptHash::new(script_hash))
            .await
            .unwrap();
        assert_eq!(response.len(), 1);
        assert_eq!(response[0].script_hash, script_hash);
    }

    // Add more tests for other endpoints...
}