Files
khadhroony-bobobot/kb_lib/src/db/dtos/onchain_observation.rs
2026-04-24 05:47:31 +02:00

105 lines
3.7 KiB
Rust

// file: kb_lib/src/db/dtos/onchain_observation.rs
//! On-chain observation DTO.
/// Application-facing on-chain observation DTO.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct KbOnchainObservationDto {
/// Optional numeric primary key.
pub id: std::option::Option<i64>,
/// Observation kind.
pub observation_kind: std::string::String,
/// Observation source family.
pub source_kind: crate::KbObservationSourceKind,
/// Optional source endpoint logical name.
pub endpoint_name: std::option::Option<std::string::String>,
/// Logical object key, for example a mint, signature or pool address.
pub object_key: std::string::String,
/// Optional slot number.
pub slot: std::option::Option<u64>,
/// Raw JSON payload.
pub payload: serde_json::Value,
/// Observation timestamp.
pub observed_at: chrono::DateTime<chrono::Utc>,
}
impl KbOnchainObservationDto {
/// Creates a new on-chain observation DTO with the current timestamp.
pub fn new(
observation_kind: std::string::String,
source_kind: crate::KbObservationSourceKind,
endpoint_name: std::option::Option<std::string::String>,
object_key: std::string::String,
slot: std::option::Option<u64>,
payload: serde_json::Value,
) -> Self {
Self {
id: None,
observation_kind,
source_kind,
endpoint_name,
object_key,
slot,
payload,
observed_at: chrono::Utc::now(),
}
}
}
impl TryFrom<crate::KbOnchainObservationEntity> for KbOnchainObservationDto {
type Error = crate::KbError;
fn try_from(entity: crate::KbOnchainObservationEntity) -> Result<Self, Self::Error> {
let source_kind_result = crate::KbObservationSourceKind::from_i16(entity.source_kind);
let source_kind = match source_kind_result {
Ok(source_kind) => source_kind,
Err(error) => return Err(error),
};
let observed_at_result = chrono::DateTime::parse_from_rfc3339(&entity.observed_at);
let observed_at = match observed_at_result {
Ok(observed_at) => observed_at.with_timezone(&chrono::Utc),
Err(error) => {
return Err(crate::KbError::Db(format!(
"cannot parse on-chain observation observed_at '{}': {}",
entity.observed_at, error
)));
}
};
let payload_result = serde_json::from_str::<serde_json::Value>(&entity.payload_json);
let payload = match payload_result {
Ok(payload) => payload,
Err(error) => {
return Err(crate::KbError::Db(format!(
"cannot parse on-chain observation payload_json '{}': {}",
entity.payload_json, error
)));
}
};
let slot = match entity.slot {
Some(slot) => {
let slot_result = u64::try_from(slot);
match slot_result {
Ok(slot) => Some(slot),
Err(error) => {
return Err(crate::KbError::Db(format!(
"cannot convert on-chain observation slot '{}' to u64: {}",
slot, error
)));
}
}
}
None => None,
};
Ok(Self {
id: Some(entity.id),
observation_kind: entity.observation_kind,
source_kind,
endpoint_name: entity.endpoint_name,
object_key: entity.object_key,
slot,
payload,
observed_at,
})
}
}