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