kaspa_wrpc_server/
address.rs

1use crate::service::WrpcEncoding;
2use kaspa_consensus_core::network::NetworkType;
3use kaspa_utils::networking::ContextualNetAddress;
4use serde::Deserialize;
5use std::{net::AddrParseError, str::FromStr};
6
7#[derive(Clone, Debug, Deserialize)]
8#[serde(rename = "lowercase")]
9pub enum WrpcNetAddress {
10    Default,
11    Public,
12    Custom(ContextualNetAddress),
13}
14
15impl WrpcNetAddress {
16    pub fn to_address(&self, network_type: &NetworkType, encoding: &WrpcEncoding) -> ContextualNetAddress {
17        match self {
18            WrpcNetAddress::Default => {
19                let port = match encoding {
20                    WrpcEncoding::Borsh => network_type.default_borsh_rpc_port(),
21                    WrpcEncoding::SerdeJson => network_type.default_json_rpc_port(),
22                };
23                format!("127.0.0.1:{port}").parse().unwrap()
24            }
25            WrpcNetAddress::Public => {
26                let port = match encoding {
27                    WrpcEncoding::Borsh => network_type.default_borsh_rpc_port(),
28                    WrpcEncoding::SerdeJson => network_type.default_json_rpc_port(),
29                };
30                format!("0.0.0.0:{port}").parse().unwrap()
31            }
32            WrpcNetAddress::Custom(address) => {
33                if address.port_not_specified() {
34                    let port = match encoding {
35                        WrpcEncoding::Borsh => network_type.default_borsh_rpc_port(),
36                        WrpcEncoding::SerdeJson => network_type.default_json_rpc_port(),
37                    };
38                    address.with_port(port)
39                } else {
40                    *address
41                }
42            }
43        }
44    }
45}
46impl FromStr for WrpcNetAddress {
47    type Err = AddrParseError;
48    fn from_str(s: &str) -> Result<Self, Self::Err> {
49        match s {
50            "default" => Ok(WrpcNetAddress::Default),
51            "public" => Ok(WrpcNetAddress::Public),
52            _ => {
53                let addr: ContextualNetAddress = s.parse()?;
54                Ok(Self::Custom(addr))
55            }
56        }
57    }
58}
59
60impl TryFrom<&str> for WrpcNetAddress {
61    type Error = AddrParseError;
62
63    fn try_from(s: &str) -> Result<Self, Self::Error> {
64        WrpcNetAddress::from_str(s)
65    }
66}
67
68impl TryFrom<String> for WrpcNetAddress {
69    type Error = AddrParseError;
70
71    fn try_from(s: String) -> Result<Self, Self::Error> {
72        WrpcNetAddress::from_str(&s)
73    }
74}
75
76#[cfg(test)]
77mod tests {
78    use super::*;
79    use kaspa_utils::networking::IpAddress;
80
81    #[test]
82    fn test_wrpc_net_address_from_str() {
83        // Addresses
84        let port: u16 = 8080;
85        let addr = format!("1.2.3.4:{port}").parse::<WrpcNetAddress>().unwrap();
86        let addr_without_port = "1.2.3.4".parse::<WrpcNetAddress>().unwrap();
87        let ip_addr = "1.2.3.4".parse::<IpAddress>().unwrap();
88        // Test
89        for schema in WrpcEncoding::iter() {
90            for network in NetworkType::iter() {
91                let expected_port = match schema {
92                    WrpcEncoding::Borsh => Some(network.default_borsh_rpc_port()),
93                    WrpcEncoding::SerdeJson => Some(network.default_json_rpc_port()),
94                };
95                // Custom address with port
96                assert_eq!(addr.to_address(&network, schema), ContextualNetAddress::new(ip_addr, Some(port)));
97                // Custom address without port
98                assert_eq!(addr_without_port.to_address(&network, schema), ContextualNetAddress::new(ip_addr, expected_port))
99            }
100        }
101    }
102}