hopr_internal_types/
lib.rs

1//! This crate contains all types that are specific to the HOPR protocol.
2//! As opposed to `hopr-primitive-types` which contains more generic types (not necessarily specific only to HOPR).
3
4use std::fmt::Formatter;
5
6use hopr_crypto_types::prelude::OffchainPublicKey;
7use hopr_primitive_types::{
8    errors::GeneralError,
9    prelude::{Address, BytesRepresentable},
10};
11
12/// Contains all types related to node identities.
13pub mod account;
14/// Implements types for on-chain announcement of nodes.
15pub mod announcement;
16/// Implements types related to HOPR payment channels.
17pub mod channels;
18/// Enumerates all errors in this crate.
19pub mod errors;
20/// Types related to internal HOPR protocol logic.
21pub mod protocol;
22/// Implements types for tickets.
23pub mod tickets;
24
25/// Uniquely identifies a HOPR node either by its [`Address`] or [`OffchainPublicKey`].
26#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, strum::EnumIs, strum::EnumTryAs)]
27#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
28pub enum NodeId {
29    /// Node represented by its on-chain [`Address`].
30    Chain(Address),
31    /// Node represented by its off-chain [`OffchainPublicKey`].
32    Offchain(OffchainPublicKey),
33}
34
35impl From<Address> for NodeId {
36    fn from(value: Address) -> Self {
37        Self::Chain(value)
38    }
39}
40
41impl From<OffchainPublicKey> for NodeId {
42    fn from(value: OffchainPublicKey) -> Self {
43        Self::Offchain(value)
44    }
45}
46
47impl TryFrom<NodeId> for Address {
48    type Error = GeneralError;
49
50    fn try_from(value: NodeId) -> Result<Self, Self::Error> {
51        value.try_as_chain().ok_or(GeneralError::InvalidInput)
52    }
53}
54
55impl TryFrom<NodeId> for OffchainPublicKey {
56    type Error = GeneralError;
57
58    fn try_from(value: NodeId) -> Result<Self, Self::Error> {
59        value.try_as_offchain().ok_or(GeneralError::InvalidInput)
60    }
61}
62
63impl std::fmt::Display for NodeId {
64    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
65        match self {
66            NodeId::Chain(a) => a.fmt(f),
67            NodeId::Offchain(a) => a.fmt(f),
68        }
69    }
70}
71
72impl std::str::FromStr for NodeId {
73    type Err = GeneralError;
74
75    fn from_str(s: &str) -> Result<Self, Self::Err> {
76        if s.len() < OffchainPublicKey::SIZE * 2 {
77            Ok(Self::Chain(s.parse()?))
78        } else {
79            Ok(Self::Offchain(s.parse()?))
80        }
81    }
82}
83
84#[doc(hidden)]
85pub mod prelude {
86    pub use super::{
87        NodeId, account::*, announcement::*, channels::*, errors::CoreTypesError, protocol::*, tickets::*,
88    };
89}
90
91#[cfg(test)]
92mod tests {
93    use std::str::FromStr;
94
95    use hopr_crypto_types::prelude::*;
96
97    use super::*;
98
99    #[test]
100    fn test_node_id_display_from_str() -> anyhow::Result<()> {
101        let offchain = OffchainKeypair::random().public().clone();
102        let onchain = ChainKeypair::random().public().to_address();
103
104        let n1 = NodeId::from_str(&offchain.to_string())?;
105        let n2 = NodeId::from_str(&onchain.to_string())?;
106
107        assert_eq!(n1, NodeId::Offchain(offchain));
108        assert_eq!(n2, NodeId::Chain(onchain));
109
110        assert_eq!(n1.to_string(), offchain.to_string());
111        assert_eq!(n2.to_string(), onchain.to_string());
112
113        Ok(())
114    }
115}