1use 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}