1use libp2p_identity::PeerId;
6use serde::{Deserialize, Serialize};
7use std::fmt::{Debug, Display, Formatter};
8use std::str::FromStr;
9use utoipa::ToSchema;
10
11use core::result::Result;
12use hopr_crypto_types::types::OffchainPublicKey;
13use hopr_db_api::prelude::HoprDbResolverOperations;
14use hopr_lib::{Address, GeneralError};
15
16use crate::ApiErrorStatus;
17
18#[derive(Debug, Clone, Copy, Eq, Hash, Ord, Serialize, Deserialize, PartialEq, PartialOrd, ToSchema)]
19pub enum PeerOrAddress {
20 #[schema(value_type = String)]
21 PeerId(PeerId),
22 #[schema(value_type = String)]
23 Address(Address),
24}
25
26impl From<PeerId> for PeerOrAddress {
27 fn from(peer_id: PeerId) -> Self {
28 Self::PeerId(peer_id)
29 }
30}
31
32impl From<Address> for PeerOrAddress {
33 fn from(address: Address) -> Self {
34 Self::Address(address)
35 }
36}
37impl FromStr for PeerOrAddress {
38 type Err = GeneralError;
39
40 fn from_str(value: &str) -> Result<PeerOrAddress, GeneralError> {
41 if value.starts_with("0x") {
42 Address::from_str(value)
43 .map(PeerOrAddress::from)
44 .map_err(|_e| GeneralError::ParseError("PeerOrAddress".into()))
45 } else {
46 PeerId::from_str(value)
47 .map(PeerOrAddress::from)
48 .map_err(|_e| GeneralError::ParseError("PeerOrAddress".into()))
49 }
50 }
51}
52
53impl Display for PeerOrAddress {
54 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
55 match self {
56 PeerOrAddress::PeerId(peer_id) => write!(f, "{}", peer_id),
57 PeerOrAddress::Address(address) => write!(f, "{}", address),
58 }
59 }
60}
61
62pub struct HoprIdentifier {
63 pub peer_id: PeerId,
64 pub address: Address,
65}
66
67impl HoprIdentifier {
68 pub async fn new_with<T: HoprDbResolverOperations>(
69 peer_or_address: PeerOrAddress,
70 resolver: &T,
71 ) -> Result<Self, ApiErrorStatus> {
72 match peer_or_address {
73 PeerOrAddress::PeerId(peer_id) => {
74 let offchain_key = match OffchainPublicKey::try_from(peer_id) {
75 Ok(key) => key,
76 Err(_) => return Err(ApiErrorStatus::InvalidInput),
77 };
78
79 match resolver.resolve_chain_key(&offchain_key).await {
80 Ok(Some(address)) => Ok(HoprIdentifier { peer_id, address }),
81 Ok(None) => Err(ApiErrorStatus::PeerNotFound),
82 Err(_) => Err(ApiErrorStatus::PeerNotFound),
83 }
84 }
85 PeerOrAddress::Address(address) => match resolver.resolve_packet_key(&address).await {
86 Ok(Some(offchain_key)) => Ok(HoprIdentifier {
87 peer_id: PeerId::from(offchain_key),
88 address,
89 }),
90 Ok(None) => Err(ApiErrorStatus::PeerNotFound),
91 Err(_) => Err(ApiErrorStatus::PeerNotFound),
92 },
93 }
94 }
95}