hopr_db_entity/conversions/
channels.rs

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