// file: kb_lib/src/db/dtos/trade_event.rs //! Trade-event DTO. /// Application-facing trade-event DTO. #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct TradeEventDto { /// Optional numeric primary key. pub id: std::option::Option, /// Related DEX id. pub dex_id: i64, /// Related pool id. pub pool_id: i64, /// Related pair id. pub pair_id: i64, /// Related transaction id. pub transaction_id: i64, /// Related decoded event id. pub decoded_event_id: i64, /// Related transaction signature. pub signature: std::string::String, /// Optional observed slot. pub slot: std::option::Option, /// Stable trade side. pub trade_side: crate::SwapTradeSide, /// Related base token id. pub base_token_id: i64, /// Related quote token id. pub quote_token_id: i64, /// Optional raw base amount. pub base_amount_raw: std::option::Option, /// Optional raw quote amount. pub quote_amount_raw: std::option::Option, /// Optional derived quote-per-base price. pub price_quote_per_base: std::option::Option, /// Observation source kind. pub source_kind: crate::ObservationSourceKind, /// Optional logical source endpoint name. pub source_endpoint_name: std::option::Option, /// Persisted payload JSON. pub payload_json: std::string::String, /// Creation timestamp. pub created_at: chrono::DateTime, /// Update timestamp. pub updated_at: chrono::DateTime, } impl TradeEventDto { /// Creates a new trade-event DTO. pub fn new( dex_id: i64, pool_id: i64, pair_id: i64, transaction_id: i64, decoded_event_id: i64, signature: std::string::String, slot: std::option::Option, trade_side: crate::SwapTradeSide, base_token_id: i64, quote_token_id: i64, base_amount_raw: std::option::Option, quote_amount_raw: std::option::Option, price_quote_per_base: std::option::Option, source_kind: crate::ObservationSourceKind, source_endpoint_name: std::option::Option, payload_json: std::string::String, ) -> Self { let now = chrono::Utc::now(); return Self { id: None, dex_id, pool_id, pair_id, transaction_id, decoded_event_id, signature, slot, trade_side, base_token_id, quote_token_id, base_amount_raw, quote_amount_raw, price_quote_per_base, source_kind, source_endpoint_name, payload_json, created_at: now, updated_at: now, }; } } impl TryFrom for TradeEventDto { type Error = crate::Error; fn try_from(entity: crate::TradeEventEntity) -> Result { let trade_side = trade_side_from_string(entity.trade_side.as_str()); let source_kind_result = crate::ObservationSourceKind::from_i16(entity.source_kind); let source_kind = match source_kind_result { Ok(source_kind) => source_kind, 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::Error::Db(format!( "cannot parse trade_event created_at '{}': {}", entity.created_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::Error::Db(format!( "cannot parse trade_event updated_at '{}': {}", entity.updated_at, error ))); }, }; return Ok(Self { id: Some(entity.id), dex_id: entity.dex_id, pool_id: entity.pool_id, pair_id: entity.pair_id, transaction_id: entity.transaction_id, decoded_event_id: entity.decoded_event_id, signature: entity.signature, slot: entity.slot, trade_side, base_token_id: entity.base_token_id, quote_token_id: entity.quote_token_id, base_amount_raw: entity.base_amount_raw, quote_amount_raw: entity.quote_amount_raw, price_quote_per_base: entity.price_quote_per_base, source_kind, source_endpoint_name: entity.source_endpoint_name, payload_json: entity.payload_json, created_at, updated_at, }); } } fn trade_side_from_string(value: &str) -> crate::SwapTradeSide { match value { "BuyBase" => return crate::SwapTradeSide::BuyBase, "SellBase" => return crate::SwapTradeSide::SellBase, _ => return crate::SwapTradeSide::Unknown, } }