This commit is contained in:
2026-04-24 08:53:40 +02:00
parent a7030d7d0f
commit 54778373b8
31 changed files with 1706 additions and 164 deletions

View File

@@ -0,0 +1,104 @@
// file: kb_lib/src/db/dtos/pool_listing.rs
//! Pool listing DTO.
/// Application-facing normalized pool listing DTO.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct KbPoolListingDto {
/// Optional numeric primary key.
pub id: std::option::Option<i64>,
/// Related DEX id.
pub dex_id: i64,
/// Related pool id.
pub pool_id: i64,
/// Optional related pair id.
pub pair_id: std::option::Option<i64>,
/// Discovery source family.
pub source_kind: crate::KbObservationSourceKind,
/// Optional source endpoint logical name.
pub source_endpoint_name: std::option::Option<std::string::String>,
/// Detection timestamp.
pub detected_at: chrono::DateTime<chrono::Utc>,
/// Optional initial base reserve estimate.
pub initial_base_reserve: std::option::Option<f64>,
/// Optional initial quote reserve estimate.
pub initial_quote_reserve: std::option::Option<f64>,
/// Optional initial price estimate in quote units.
pub initial_price_quote: std::option::Option<f64>,
/// Update timestamp.
pub updated_at: chrono::DateTime<chrono::Utc>,
}
impl KbPoolListingDto {
/// Creates a new pool listing DTO.
pub fn new(
dex_id: i64,
pool_id: i64,
pair_id: std::option::Option<i64>,
source_kind: crate::KbObservationSourceKind,
source_endpoint_name: std::option::Option<std::string::String>,
initial_base_reserve: std::option::Option<f64>,
initial_quote_reserve: std::option::Option<f64>,
initial_price_quote: std::option::Option<f64>,
) -> Self {
let now = chrono::Utc::now();
Self {
id: None,
dex_id,
pool_id,
pair_id,
source_kind,
source_endpoint_name,
detected_at: now,
initial_base_reserve,
initial_quote_reserve,
initial_price_quote,
updated_at: now,
}
}
}
impl TryFrom<crate::KbPoolListingEntity> for KbPoolListingDto {
type Error = crate::KbError;
fn try_from(entity: crate::KbPoolListingEntity) -> 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 detected_at_result = chrono::DateTime::parse_from_rfc3339(&entity.detected_at);
let detected_at = match detected_at_result {
Ok(detected_at) => detected_at.with_timezone(&chrono::Utc),
Err(error) => {
return Err(crate::KbError::Db(format!(
"cannot parse pool_listing detected_at '{}': {}",
entity.detected_at, error
)));
}
};
let updated_at_result = chrono::DateTime::parse_from_rfc3339(&entity.updated_at);
let updated_at = match updated_at_result {
Ok(updated_at) => updated_at.with_timezone(&chrono::Utc),
Err(error) => {
return Err(crate::KbError::Db(format!(
"cannot parse pool_listing updated_at '{}': {}",
entity.updated_at, error
)));
}
};
Ok(Self {
id: Some(entity.id),
dex_id: entity.dex_id,
pool_id: entity.pool_id,
pair_id: entity.pair_id,
source_kind,
source_endpoint_name: entity.source_endpoint_name,
detected_at,
initial_base_reserve: entity.initial_base_reserve,
initial_quote_reserve: entity.initial_quote_reserve,
initial_price_quote: entity.initial_price_quote,
updated_at,
})
}
}