hopr_db_entity/conversions/
channels.rs

1use crate::channel;
2use crate::errors::DbEntityError;
3use hopr_internal_types::channels::ChannelStatus;
4use hopr_internal_types::prelude::ChannelEntry;
5use hopr_primitive_types::prelude::{BalanceType, IntoEndian, ToHex, U256};
6use sea_orm::Set;
7
8/// Extension trait for updating [ChannelStatus] inside [channel::ActiveModel].
9/// This is needed as `status` maps to two model members.
10pub trait ChannelStatusUpdate {
11    /// Update [ChannelStatus] of this active model.
12    fn set_status(&mut self, new_status: ChannelStatus);
13}
14
15impl ChannelStatusUpdate for channel::ActiveModel {
16    fn set_status(&mut self, new_status: ChannelStatus) {
17        self.status = Set(i8::from(new_status));
18        if let ChannelStatus::PendingToClose(t) = new_status {
19            self.closure_time = Set(Some(chrono::DateTime::<chrono::Utc>::from(t)))
20        }
21    }
22}
23
24impl TryFrom<&channel::Model> for ChannelStatus {
25    type Error = DbEntityError;
26
27    fn try_from(value: &channel::Model) -> Result<Self, Self::Error> {
28        match value.status {
29            0 => Ok(ChannelStatus::Closed),
30            1 => Ok(ChannelStatus::Open),
31            2 => value
32                .closure_time
33                .ok_or(DbEntityError::ConversionError(
34                    "channel is pending to close but without closure time".into(),
35                ))
36                .map(|time| ChannelStatus::PendingToClose(time.into())),
37            _ => Err(DbEntityError::ConversionError("invalid channel status value".into())),
38        }
39    }
40}
41
42impl TryFrom<&channel::Model> for ChannelEntry {
43    type Error = DbEntityError;
44
45    fn try_from(value: &channel::Model) -> Result<Self, Self::Error> {
46        let status = value.try_into()?;
47        Ok(ChannelEntry::new(
48            value.source.parse()?,
49            value.destination.parse()?,
50            BalanceType::HOPR.balance_bytes(&value.balance),
51            U256::from_be_bytes(&value.ticket_index),
52            status,
53            U256::from_be_bytes(&value.epoch),
54        ))
55    }
56}
57
58impl TryFrom<channel::Model> for ChannelEntry {
59    type Error = DbEntityError;
60
61    fn try_from(value: channel::Model) -> Result<Self, Self::Error> {
62        (&value).try_into()
63    }
64}
65
66impl From<ChannelEntry> for channel::ActiveModel {
67    fn from(value: ChannelEntry) -> Self {
68        let mut ret = channel::ActiveModel {
69            channel_id: Set(value.get_id().to_hex()),
70            source: Set(value.source.to_hex()),
71            destination: Set(value.destination.to_hex()),
72            balance: Set(value.balance.amount().to_be_bytes().into()),
73            epoch: Set(value.channel_epoch.to_be_bytes().into()),
74            ticket_index: Set(value.ticket_index.to_be_bytes().into()),
75            ..Default::default()
76        };
77        ret.set_status(value.status);
78        ret
79    }
80}