// Copyright 2023 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 // due to the code generated by Tsify #![allow(clippy::empty_docs)] use crate::node::{EntryDetails, RoutingNode, RoutingNodeError, SupportedRoles}; use crate::{CachedEpochRewardedSet, NymTopology, NymTopologyMetadata}; use nym_wasm_utils::error::simple_js_error; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::net::SocketAddr; use thiserror::Error; use tsify::Tsify; use wasm_bindgen::{JsValue, prelude::wasm_bindgen}; #[derive(Debug, Error)] pub enum SerializableTopologyError { #[error(transparent)] NodeConversion(#[from] RoutingNodeError), #[error("{provided} is not a valid ed25519 public key")] MalformedIdentity { provided: String }, #[error("{provided} is not a valid x25519 public key")] MalformedSphinxKey { provided: String }, } #[cfg(feature = "wasm-serde-types")] impl From for JsValue { fn from(value: SerializableTopologyError) -> Self { simple_js_error(value.to_string()) } } #[derive(Debug, Clone, Serialize, Deserialize, Tsify)] #[tsify(into_wasm_abi, from_wasm_abi)] #[serde(rename_all = "camelCase")] #[serde(deny_unknown_fields)] pub struct WasmFriendlyNymTopology { pub metadata: NymTopologyMetadata, pub rewarded_set: CachedEpochRewardedSet, pub node_details: HashMap, } impl TryFrom for NymTopology { type Error = SerializableTopologyError; fn try_from(value: WasmFriendlyNymTopology) -> Result { let node_details = value .node_details .into_values() .map(|details| details.try_into()) .collect::>()?; Ok(NymTopology::new( value.metadata, value.rewarded_set, node_details, )) } } impl From for WasmFriendlyNymTopology { fn from(value: NymTopology) -> Self { WasmFriendlyNymTopology { metadata: value.metadata, rewarded_set: value.rewarded_set, node_details: value .node_details .into_iter() .map(|(k, v)| (k, v.into())) .collect(), } } } #[derive(Debug, Clone, Serialize, Deserialize, Tsify)] #[tsify(into_wasm_abi, from_wasm_abi)] #[serde(rename_all = "camelCase")] #[serde(deny_unknown_fields)] pub struct WasmFriendlyRoutingNode { pub node_id: u32, pub mix_host: SocketAddr, pub entry: Option, pub identity_key: String, pub sphinx_key: String, pub supported_roles: SupportedRoles, } impl TryFrom for RoutingNode { type Error = SerializableTopologyError; fn try_from(value: WasmFriendlyRoutingNode) -> Result { Ok(RoutingNode { node_id: value.node_id, mix_host: value.mix_host, entry: value.entry, identity_key: value.identity_key.as_str().parse().map_err(|_| { SerializableTopologyError::MalformedIdentity { provided: value.identity_key, } })?, sphinx_key: value.sphinx_key.as_str().parse().map_err(|_| { SerializableTopologyError::MalformedIdentity { provided: value.sphinx_key, } })?, supported_roles: value.supported_roles, }) } } impl From for WasmFriendlyRoutingNode { fn from(node: RoutingNode) -> Self { WasmFriendlyRoutingNode { node_id: node.node_id, mix_host: node.mix_host, entry: node.entry, identity_key: node.identity_key.to_string(), sphinx_key: node.sphinx_key.to_string(), supported_roles: node.supported_roles, } } }