From 346c4f79108d742b870f2b4c1e457b8a13c0c86e Mon Sep 17 00:00:00 2001 From: dynco-nym <173912580+dynco-nym@users.noreply.github.com> Date: Fri, 29 Nov 2024 18:51:00 +0100 Subject: [PATCH] Add latitude/longitude fields to Location --- Cargo.lock | 2 +- .../nym-node-status-api/Cargo.toml | 2 +- .../src/monitor/geodata.rs | 65 +++++++++++++++---- 3 files changed, 54 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 936dadfbd6..dbe2ccf375 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6061,7 +6061,7 @@ dependencies = [ [[package]] name = "nym-node-status-api" -version = "1.0.0-rc.4" +version = "1.0.0-rc.4-fix" dependencies = [ "anyhow", "axum 0.7.7", diff --git a/nym-node-status-api/nym-node-status-api/Cargo.toml b/nym-node-status-api/nym-node-status-api/Cargo.toml index 05d1586ae9..5594b1d329 100644 --- a/nym-node-status-api/nym-node-status-api/Cargo.toml +++ b/nym-node-status-api/nym-node-status-api/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "nym-node-status-api" -version = "1.0.0-rc.4" +version = "1.0.0-rc.4-fix" authors.workspace = true repository.workspace = true homepage.workspace = true diff --git a/nym-node-status-api/nym-node-status-api/src/monitor/geodata.rs b/nym-node-status-api/nym-node-status-api/src/monitor/geodata.rs index 1042b15cce..93e0077171 100644 --- a/nym-node-status-api/nym-node-status-api/src/monitor/geodata.rs +++ b/nym-node-status-api/nym-node-status-api/src/monitor/geodata.rs @@ -1,5 +1,5 @@ use cosmwasm_std::{Addr, Coin}; -use serde::{Deserialize, Serialize}; +use serde::{Deserialize, Deserializer, Serialize}; pub(crate) struct IpInfoClient { client: reqwest::Client, @@ -15,11 +15,7 @@ impl IpInfoClient { } pub(crate) async fn locate_ip(&self, ip: impl AsRef) -> anyhow::Result { - let url = format!( - "https://ipinfo.io/{}/country?token={}", - ip.as_ref(), - &self.token - ); + let url = format!("https://ipinfo.io/{}?token={}", ip.as_ref(), &self.token); let response = self .client .get(url) @@ -33,11 +29,12 @@ impl IpInfoClient { } anyhow::Error::from(err) })?; - let response_text = response.text().await?.trim().to_string(); + let raw_response = response.text().await?; + let response: LocationResponse = + serde_json::from_str(&raw_response).inspect_err(|e| tracing::error!("{e}"))?; + let location = response.into(); - Ok(Location { - two_letter_iso_country_code: response_text, - }) + Ok(location) } /// check DOESN'T consume bandwidth allowance @@ -64,7 +61,7 @@ impl IpInfoClient { } } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize)] pub(crate) struct NodeGeoData { pub(crate) identity_key: String, pub(crate) owner: Addr, @@ -72,15 +69,57 @@ pub(crate) struct NodeGeoData { pub(crate) location: Location, } -#[derive(Debug, Clone, Default, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize)] pub(crate) struct Location { pub(crate) two_letter_iso_country_code: String, + #[serde(flatten)] + pub(crate) location: Coordinates, +} + +impl From for Location { + fn from(value: LocationResponse) -> Self { + Self { + two_letter_iso_country_code: value.two_letter_iso_country_code, + location: value.loc, + } + } +} + +#[derive(Debug, Clone, Deserialize)] +pub(crate) struct LocationResponse { + #[serde(rename = "country")] + pub(crate) two_letter_iso_country_code: String, + #[serde(deserialize_with = "deserialize_loc")] + pub(crate) loc: Coordinates, +} + +fn deserialize_loc<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + let loc_raw = String::deserialize(deserializer)?; + return match loc_raw.split_once(',') { + Some((lat, long)) => Ok(Coordinates { + latitude: lat.parse().map_err(|err| serde::de::Error::custom(err))?, + longitude: long.parse().map_err(|err| serde::de::Error::custom(err))?, + }), + None => Err(serde::de::Error::custom("coordinates")), + }; +} + +#[derive(Debug, Default, Clone, Serialize, Deserialize)] +pub(crate) struct Coordinates { + pub(crate) latitude: f64, + pub(crate) longitude: f64, } impl Location { pub(crate) fn empty() -> Self { Self { - two_letter_iso_country_code: String::new(), + two_letter_iso_country_code: String::default(), + location: Coordinates { + ..Default::default() + }, } } }