matroskin 0.1.0

whatsminer api client lib
Documentation
//! Implement `get.miner.history` command
//!
//! This command is used to retrieve historical performance data for the miner
//! within a specified time range.
//!
//! The time range between `begin` and `end` cannot exceed 24 hours.
//!
//! - Command: [GetMinerHistory]
//! - ApiDoc: <https://apidoc.whatsminer.com/#api-Miner-get_miner_history>

use serde::{Serialize, Serializer};

use crate::{
    command::{Command, CommandLevel},
    error::Result,
    permission::PermissionLevel,
};

/// This command represents the `get.miner.history` operation.
///
/// It is used to retrieve historical performance data for the miner
/// within a specified time range.
///
/// The time range between `begin` and `end` cannot exceed 24 hours.
///
/// - ApiDoc: <https://apidoc.whatsminer.com/#api-Miner-get_miner_history>
///
/// # Example
/// ```rust,no_run
/// use matroskin::actor::Actor;
/// use matroskin::command::get_miner_history::GetMinerHistory;
/// use matroskin::account::Account;
/// use matroskin::password::Password;
///
/// #[tokio::main]
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
///     let addr = "10.10.10.10:4433";
///     let username = Account::Super;
///     let password = Password::Super;
///
///     let actor = Actor::new(addr, username, password);
///     actor.connect()?;
///
///     let cmd = GetMinerHistory::new(1672000000, 1672280000);
///     let response = actor.send(cmd).await?;
///     println!("History: {:#?}", response);
///
///     Ok(())
/// }
/// ```
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct GetMinerHistory {
    /// Start of the time range as a Unix timestamp.
    pub begin: u64,
    /// End of the time range as a Unix timestamp.
    pub end: u64,
}

impl GetMinerHistory {
    /// Creates a new [GetMinerHistory] with the given time range.
    pub fn new(begin: u64, end: u64) -> Self {
        Self { begin, end }
    }
}

impl Serialize for GetMinerHistory {
    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        use serde::ser::SerializeStruct;
        let mut s = serializer.serialize_struct("GetMinerHistory", 2)?;
        s.serialize_field("begin", &self.begin.to_string())?;
        s.serialize_field("end", &self.end.to_string())?;
        s.end()
    }
}

impl Command for GetMinerHistory {
    type Response = String;
    const CMD_NAME: &'static str = "get.miner.history";
    const LEVEL: CommandLevel = CommandLevel::Public;
    const MINIMAL_PERMISSIONS: PermissionLevel = PermissionLevel::ReadOnly;

    fn params(&self) -> Result<Option<impl serde::Serialize>> {
        Ok(Some(self))
    }
}

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

    const RESPONSE_JSON: &str = r#"{"code":0,"when":1672281726,"msg":"miner history information......","desc":"get.miner.history"}"#;

    #[test]
    fn param_serializes_timestamps_as_strings() {
        let cmd = GetMinerHistory::new(1672000000, 1672280000);
        let json = serde_json::to_string(&cmd).unwrap();
        assert_eq!(json, r#"{"begin":"1672000000","end":"1672280000"}"#);
    }

    #[test]
    fn request_has_param_no_auth() {
        let cmd = GetMinerHistory::new(1672000000, 1672280000);
        assert!(!cmd.is_secured());
        assert!(!cmd.is_encrypted());

        let encoded = cmd.encode(None).unwrap();
        let json: serde_json::Value = serde_json::from_slice(&encoded.0).unwrap();
        assert_eq!(json["cmd"], "get.miner.history");
        assert_eq!(json["param"]["begin"], "1672000000");
        assert_eq!(json["param"]["end"], "1672280000");
        // no auth fields for Public command
        assert!(json.get("token").is_none());
        assert!(json.get("account").is_none());
    }

    #[test]
    fn deserialize_response_fixture() {
        let response = GetMinerHistory::parse_response(RESPONSE_JSON.as_bytes()).unwrap();
        assert!(response.code.is_success());
        assert_eq!(response.desc, "get.miner.history");
        assert_eq!(response.when, 1672281726);
        assert_eq!(response.msg, "miner history information......");
    }
}