nym_types/
mixnode.rs

1// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::currency::{DecCoin, RegisteredCoins};
5use crate::error::TypesError;
6use cosmwasm_std::Decimal;
7use nym_mixnet_contract_common::{
8    EpochId, MixNode, MixNodeBond as MixnetContractMixNodeBond,
9    MixNodeDetails as MixnetContractMixNodeDetails, NodeCostParams as MixnetContractNodeCostParams,
10    NodeId, NodeRewarding as MixnetContractNodeRewarding, Percent,
11};
12use schemars::JsonSchema;
13use serde::{Deserialize, Serialize};
14use std::fmt;
15use std::net::IpAddr;
16
17#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
18#[cfg_attr(
19    feature = "generate-ts",
20    ts(
21        export,
22        export_to = "ts-packages/types/src/types/rust/MixNodeDetails.ts"
23    )
24)]
25#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
26pub struct MixNodeDetails {
27    pub bond_information: MixNodeBond,
28    pub rewarding_details: NodeRewarding,
29}
30
31impl MixNodeDetails {
32    pub fn from_mixnet_contract_mixnode_details(
33        details: MixnetContractMixNodeDetails,
34        reg: &RegisteredCoins,
35    ) -> Result<MixNodeDetails, TypesError> {
36        Ok(MixNodeDetails {
37            bond_information: MixNodeBond::from_mixnet_contract_mixnode_bond(
38                details.bond_information,
39                reg,
40            )?,
41            rewarding_details: NodeRewarding::from_mixnet_contract_node_rewarding(
42                details.rewarding_details,
43                reg,
44            )?,
45        })
46    }
47}
48
49#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
50#[cfg_attr(
51    feature = "generate-ts",
52    ts(export, export_to = "ts-packages/types/src/types/rust/MixNodeBond.ts")
53)]
54#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
55pub struct MixNodeBond {
56    pub mix_id: NodeId,
57    pub owner: String,
58    pub original_pledge: DecCoin,
59    pub mix_node: MixNode,
60    pub proxy: Option<String>,
61    pub bonding_height: u64,
62    pub is_unbonding: bool,
63}
64
65impl MixNodeBond {
66    pub fn from_mixnet_contract_mixnode_bond(
67        bond: MixnetContractMixNodeBond,
68        reg: &RegisteredCoins,
69    ) -> Result<MixNodeBond, TypesError> {
70        Ok(MixNodeBond {
71            mix_id: bond.mix_id,
72            owner: bond.owner.into_string(),
73            original_pledge: reg
74                .attempt_convert_to_display_dec_coin(bond.original_pledge.into())?,
75            mix_node: bond.mix_node,
76            proxy: bond.proxy.map(|p| p.into_string()),
77            bonding_height: bond.bonding_height,
78            is_unbonding: bond.is_unbonding,
79        })
80    }
81}
82
83#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
84#[cfg_attr(
85    feature = "generate-ts",
86    ts(
87        export,
88        export_to = "ts-packages/types/src/types/rust/NodeRewarding.ts"
89    )
90)]
91#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
92pub struct NodeRewarding {
93    pub cost_params: NodeCostParams,
94
95    #[cfg_attr(feature = "generate-ts", ts(type = "string"))]
96    pub operator: Decimal,
97
98    #[cfg_attr(feature = "generate-ts", ts(type = "string"))]
99    pub delegates: Decimal,
100
101    #[cfg_attr(feature = "generate-ts", ts(type = "string"))]
102    pub total_unit_reward: Decimal,
103
104    #[cfg_attr(feature = "generate-ts", ts(type = "string"))]
105    pub unit_delegation: Decimal,
106
107    pub last_rewarded_epoch: EpochId,
108
109    pub unique_delegations: u32,
110}
111
112impl NodeRewarding {
113    pub fn from_mixnet_contract_node_rewarding(
114        mix_rewarding: MixnetContractNodeRewarding,
115        reg: &RegisteredCoins,
116    ) -> Result<NodeRewarding, TypesError> {
117        Ok(NodeRewarding {
118            cost_params: NodeCostParams::from_mixnet_contract_mixnode_cost_params(
119                mix_rewarding.cost_params,
120                reg,
121            )?,
122            operator: mix_rewarding.operator,
123            delegates: mix_rewarding.delegates,
124            total_unit_reward: mix_rewarding.total_unit_reward,
125            unit_delegation: mix_rewarding.unit_delegation,
126            last_rewarded_epoch: mix_rewarding.last_rewarded_epoch,
127            unique_delegations: mix_rewarding.unique_delegations,
128        })
129    }
130}
131
132#[cfg_attr(feature = "generate-ts", derive(ts_rs::TS))]
133#[cfg_attr(
134    feature = "generate-ts",
135    ts(
136        export,
137        export_to = "ts-packages/types/src/types/rust/MixNodeCostParams.ts"
138    )
139)]
140#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, JsonSchema)]
141pub struct NodeCostParams {
142    #[cfg_attr(feature = "generate-ts", ts(type = "string"))]
143    pub profit_margin_percent: Percent,
144
145    pub interval_operating_cost: DecCoin,
146}
147
148impl NodeCostParams {
149    pub fn from_mixnet_contract_mixnode_cost_params(
150        cost_params: MixnetContractNodeCostParams,
151        reg: &RegisteredCoins,
152    ) -> Result<NodeCostParams, TypesError> {
153        Ok(NodeCostParams {
154            profit_margin_percent: cost_params.profit_margin_percent,
155            interval_operating_cost: reg
156                .attempt_convert_to_display_dec_coin(cost_params.interval_operating_cost.into())?,
157        })
158    }
159
160    pub fn try_convert_to_mixnet_contract_cost_params(
161        self,
162        reg: &RegisteredCoins,
163    ) -> Result<MixnetContractNodeCostParams, TypesError> {
164        Ok(MixnetContractNodeCostParams {
165            profit_margin_percent: self.profit_margin_percent,
166            interval_operating_cost: reg
167                .attempt_convert_to_base_coin(self.interval_operating_cost)?
168                .into(),
169        })
170    }
171}
172
173#[derive(Serialize, Deserialize)]
174pub struct MixnodeNodeDetailsResponse {
175    pub identity_key: String,
176    pub sphinx_key: String,
177    pub bind_address: IpAddr,
178    pub version: String,
179    pub mix_port: u16,
180    pub http_api_port: u16,
181    pub verloc_port: u16,
182}
183
184impl fmt::Display for MixnodeNodeDetailsResponse {
185    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
186        writeln!(f, "Identity Key: {}", self.identity_key)?;
187        writeln!(f, "Sphinx Key: {}", self.sphinx_key)?;
188        writeln!(f, "Host: {}", self.bind_address)?;
189        writeln!(f, "Version: {}", self.version)?;
190        writeln!(
191            f,
192            "Mix Port: {}, Verloc port: {}, Http Port: {}\n",
193            self.mix_port, self.verloc_port, self.http_api_port
194        )
195    }
196}