// file: kb_lib/src/db/dtos/analysis_signal.rs //! Analysis signal DTO. /// Application-facing analysis signal DTO. #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct KbAnalysisSignalDto { /// Optional numeric primary key. pub id: std::option::Option, /// Signal kind. pub signal_kind: std::string::String, /// Signal severity. pub severity: crate::KbAnalysisSignalSeverity, /// Logical object key, for example a mint, signature or pool address. pub object_key: std::string::String, /// Optional related on-chain observation id. pub related_observation_id: std::option::Option, /// Optional numeric score. pub score: std::option::Option, /// Signal payload. pub payload: serde_json::Value, /// Creation timestamp. pub created_at: chrono::DateTime, } impl KbAnalysisSignalDto { /// Creates a new analysis signal DTO with the current timestamp. pub fn new( signal_kind: std::string::String, severity: crate::KbAnalysisSignalSeverity, object_key: std::string::String, related_observation_id: std::option::Option, score: std::option::Option, payload: serde_json::Value, ) -> Self { Self { id: None, signal_kind, severity, object_key, related_observation_id, score, payload, created_at: chrono::Utc::now(), } } } impl TryFrom for KbAnalysisSignalDto { type Error = crate::KbError; fn try_from(entity: crate::KbAnalysisSignalEntity) -> Result { let severity_result = crate::KbAnalysisSignalSeverity::from_i16(entity.severity); let severity = match severity_result { Ok(severity) => severity, Err(error) => return Err(error), }; let created_at_result = chrono::DateTime::parse_from_rfc3339(&entity.created_at); let created_at = match created_at_result { Ok(created_at) => created_at.with_timezone(&chrono::Utc), Err(error) => { return Err(crate::KbError::Db(format!( "cannot parse analysis signal created_at '{}': {}", entity.created_at, error ))); } }; let payload_result = serde_json::from_str::(&entity.payload_json); let payload = match payload_result { Ok(payload) => payload, Err(error) => { return Err(crate::KbError::Db(format!( "cannot parse analysis signal payload_json '{}': {}", entity.payload_json, error ))); } }; Ok(Self { id: Some(entity.id), signal_kind: entity.signal_kind, severity, object_key: entity.object_key, related_observation_id: entity.related_observation_id, score: entity.score, payload, created_at, }) } }