hopr_internal_types/
account.rs1use hopr_crypto_types::types::OffchainPublicKey;
2use hopr_primitive_types::prelude::*;
3use multiaddr::Multiaddr;
4use serde::{Deserialize, Serialize};
5use std::fmt::{Display, Formatter};
6
7#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
9pub enum AccountType {
10 NotAnnounced,
12 Announced { multiaddr: Multiaddr, updated_block: u32 },
14}
15
16impl Display for AccountType {
17 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
18 match &self {
19 Self::NotAnnounced => {
20 write!(f, "Not announced")
21 }
22 Self::Announced {
23 multiaddr,
24 updated_block,
25 } => f
26 .debug_struct("AccountType")
27 .field("MultiAddr", multiaddr)
28 .field("UpdatedAt", updated_block)
29 .finish(),
30 }
31 }
32}
33
34#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
37pub struct AccountEntry {
38 pub public_key: OffchainPublicKey,
39 pub chain_addr: Address,
40 pub entry_type: AccountType,
41}
42
43impl AccountEntry {
44 pub fn new(public_key: OffchainPublicKey, address: Address, entry_type: AccountType) -> Self {
45 Self {
46 public_key,
47 chain_addr: address,
48 entry_type,
49 }
50 }
51
52 pub fn updated_at(&self) -> Option<u32> {
54 match &self.entry_type {
55 AccountType::NotAnnounced => None,
56 AccountType::Announced { updated_block, .. } => Some(*updated_block),
57 }
58 }
59
60 pub fn has_announced(&self) -> bool {
62 matches!(self.entry_type, AccountType::Announced { .. })
63 }
64
65 pub fn contains_routing_info(&self) -> bool {
67 match &self.entry_type {
68 AccountType::NotAnnounced => false,
69 AccountType::Announced { multiaddr, .. } => {
70 multiaddr.protocol_stack().any(|p| p == "ip4" || p == "dns4")
71 && multiaddr.protocol_stack().any(|p| p == "tcp")
72 }
73 }
74 }
75
76 pub fn get_multiaddr(&self) -> Option<Multiaddr> {
77 match &self.entry_type {
78 AccountType::NotAnnounced => None,
79 AccountType::Announced { multiaddr, .. } => Some(multiaddr.clone()),
80 }
81 }
82
83 pub fn update(&mut self, new_entry_type: AccountType) {
90 self.entry_type = new_entry_type;
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 use crate::account::{
97 AccountEntry,
98 AccountType::{Announced, NotAnnounced},
99 };
100 use hex_literal::hex;
101 use hopr_crypto_types::types::OffchainPublicKey;
102 use hopr_primitive_types::prelude::*;
103 use multiaddr::Multiaddr;
104
105 const PRIVATE_KEY: [u8; 32] = hex!("c14b8faa0a9b8a5fa4453664996f23a7e7de606d42297d723fc4a794f375e260");
106 const CHAIN_ADDR: [u8; 20] = hex!("2cDD13ddB0346E0F620C8E5826Da5d7230341c6E");
107
108 #[test]
109 fn test_account_entry_non_routable() -> anyhow::Result<()> {
110 let pub_key = OffchainPublicKey::from_privkey(&PRIVATE_KEY)?;
111 let chain_addr = Address::try_from(CHAIN_ADDR.as_ref())?;
112
113 let ae1 = AccountEntry::new(
114 pub_key,
115 chain_addr,
116 Announced {
117 multiaddr: "/p2p/16Uiu2HAm3rUQdpCz53tK1MVUUq9NdMAU6mFgtcXrf71Ltw6AStzk".parse::<Multiaddr>()?,
118 updated_block: 1,
119 },
120 );
121
122 assert!(ae1.has_announced());
123 assert_eq!(1, ae1.updated_at().expect("should be present"));
124 assert!(!ae1.contains_routing_info());
125
126 Ok(())
127 }
128
129 #[test]
130 fn test_account_entry_routable() -> anyhow::Result<()> {
131 let pub_key = OffchainPublicKey::from_privkey(&PRIVATE_KEY)?;
132 let chain_addr = Address::try_from(CHAIN_ADDR.as_ref())?;
133
134 let ae1 = AccountEntry::new(
135 pub_key,
136 chain_addr,
137 Announced {
138 multiaddr: "/ip4/34.65.237.196/tcp/9091/p2p/16Uiu2HAm3rUQdpCz53tK1MVUUq9NdMAU6mFgtcXrf71Ltw6AStzk"
139 .parse::<Multiaddr>()?,
140 updated_block: 1,
141 },
142 );
143
144 assert!(ae1.has_announced());
145 assert_eq!(1, ae1.updated_at().expect("should be present"));
146 assert!(ae1.contains_routing_info());
147
148 Ok(())
149 }
150
151 #[test]
152 fn test_account_entry_not_announced() -> anyhow::Result<()> {
153 let pub_key = OffchainPublicKey::from_privkey(&PRIVATE_KEY)?;
154 let chain_addr = Address::try_from(CHAIN_ADDR.as_ref())?;
155
156 let ae1 = AccountEntry::new(pub_key, chain_addr, NotAnnounced);
157
158 assert!(!ae1.has_announced());
159 assert!(ae1.updated_at().is_none());
160 assert!(!ae1.contains_routing_info());
161
162 Ok(())
163 }
164}