hopr_db_entity/conversions/
channels.rs

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