nym_cli_commands/
utils.rs1use anyhow::{anyhow, bail};
5use cosmrs::AccountId;
6use cosmwasm_std::{Addr, Coin as CosmWasmCoin, Decimal};
7use log::error;
8use nym_client_core::config::disk_persistence::CommonClientPaths;
9use nym_validator_client::nyxd::Coin;
10use serde::{Deserialize, Serialize};
11use std::error::Error;
12use std::fmt::{Display, Formatter};
13use std::fs;
14use std::path::{Path, PathBuf};
15
16pub fn account_id_to_cw_addr(account_id: &AccountId) -> Addr {
18 Addr::unchecked(account_id.as_ref())
21}
22
23pub fn pretty_coin(coin: &Coin) -> String {
24 let amount = Decimal::from_ratio(coin.amount, 1_000_000u128);
25 let denom = if coin.denom.starts_with('u') {
26 &coin.denom[1..]
27 } else {
28 &coin.denom
29 };
30 format!("{amount} {denom}")
31}
32
33pub fn pretty_cosmwasm_coin(coin: &CosmWasmCoin) -> String {
34 let amount = Decimal::from_ratio(coin.amount, 1_000_000u128);
35 let denom = if coin.denom.starts_with('u') {
36 &coin.denom[1..]
37 } else {
38 &coin.denom
39 };
40 format!("{amount} {denom}")
41}
42
43pub fn pretty_decimal_with_denom(value: Decimal, denom: &str) -> String {
44 format!("{value} {denom}")
46}
47
48pub fn show_error<E>(e: E)
49where
50 E: Display,
51{
52 error!("{e}");
53}
54
55pub fn show_error_passthrough<E>(e: E) -> E
56where
57 E: Error + Display,
58{
59 error!("{e}");
60 e
61}
62
63#[derive(Serialize)]
64pub(crate) struct DataWrapper<T> {
65 data: T,
66}
67
68impl<T> Display for DataWrapper<T>
69where
70 T: Display,
71{
72 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
73 write!(f, "{}", self.data)
74 }
75}
76
77impl<T> DataWrapper<T> {
78 pub(crate) fn new(data: T) -> Self {
79 DataWrapper { data }
80 }
81}
82
83fn find_toml_value<'a>(root: &'a toml::Value, key: &str) -> Option<&'a toml::Value> {
84 if let toml::Value::Table(table) = root {
85 for (k, v) in table {
86 if k == key {
87 return Some(v);
88 }
89 if v.is_table() {
90 if let Some(res) = find_toml_value(v, key) {
91 return Some(res);
92 }
93 }
94 }
95 }
96 None
97}
98
99#[derive(Deserialize, Debug)]
100#[serde(untagged)]
101pub(crate) enum CommonConfigsWrapper {
102 NymClients(Box<ClientConfigCommonWrapper>),
104
105 NymApi(NymApiConfigLight),
107
108 Unknown(UnknownConfigWrapper),
110}
111
112impl CommonConfigsWrapper {
113 pub(crate) fn try_load<P: AsRef<Path>>(path: P) -> anyhow::Result<CommonConfigsWrapper> {
114 let content = fs::read_to_string(path)?;
115 Ok(toml::from_str(&content)?)
116 }
117
118 pub(crate) fn try_get_id(&self) -> anyhow::Result<&str> {
119 match self {
120 CommonConfigsWrapper::NymClients(cfg) => cfg.try_get_id(),
121 CommonConfigsWrapper::NymApi(cfg) => Ok(&cfg.base.id),
122 CommonConfigsWrapper::Unknown(cfg) => cfg.try_get_id(),
123 }
124 }
125
126 pub(crate) fn try_get_private_id_key(&self) -> anyhow::Result<PathBuf> {
127 match self {
128 CommonConfigsWrapper::NymClients(cfg) => Ok(cfg
129 .storage_paths
130 .inner
131 .keys
132 .private_identity_key_file
133 .clone()),
134 CommonConfigsWrapper::NymApi(_cfg) => {
135 todo!() }
137 CommonConfigsWrapper::Unknown(cfg) => cfg.try_get_private_id_key(),
138 }
139 }
140
141 pub(crate) fn try_get_credentials_store(&self) -> anyhow::Result<PathBuf> {
142 match self {
143 CommonConfigsWrapper::NymClients(cfg) => {
144 Ok(cfg.storage_paths.inner.credentials_database.clone())
145 }
146 CommonConfigsWrapper::NymApi(cfg) => Ok(cfg
147 .network_monitor
148 .storage_paths
149 .credentials_database_path
150 .clone()),
151 CommonConfigsWrapper::Unknown(cfg) => cfg.try_get_credentials_store(),
152 }
153 }
154}
155
156#[derive(Deserialize, Debug)]
159pub(crate) struct NymApiConfigLight {
160 base: NymApiConfigBaseLight,
161 network_monitor: NymApiConfigNetworkMonitorLight,
162}
163
164#[derive(Deserialize, Debug)]
165struct NymApiConfigBaseLight {
166 id: String,
167}
168
169#[derive(Deserialize, Debug)]
170struct NymApiConfigNetworkMonitorLight {
171 storage_paths: NetworkMonitorPaths,
172}
173
174#[derive(Deserialize, Debug)]
175struct NetworkMonitorPaths {
176 credentials_database_path: PathBuf,
177}
178
179#[derive(Deserialize, Debug)]
183pub(crate) struct ClientConfigCommonWrapper {
184 storage_paths: StoragePathsWrapper,
185
186 #[serde(flatten)]
189 other: toml::Value,
190}
191
192#[derive(Deserialize, Debug)]
194struct StoragePathsWrapper {
195 #[serde(flatten)]
196 inner: CommonClientPaths,
197}
198
199impl ClientConfigCommonWrapper {
200 pub(crate) fn try_get_id(&self) -> anyhow::Result<&str> {
201 let id_val = find_toml_value(&self.other, "id")
202 .ok_or_else(|| anyhow!("no id field present in the config"))?;
203 if let toml::Value::String(id) = id_val {
204 Ok(id)
205 } else {
206 bail!("no id field present in the config")
207 }
208 }
209}
210
211#[derive(Deserialize, Debug)]
212pub(crate) struct UnknownConfigWrapper {
213 #[serde(flatten)]
214 inner: toml::Value,
215}
216
217impl UnknownConfigWrapper {
218 fn find_value(&self, key: &str) -> Option<&toml::Value> {
219 find_toml_value(&self.inner, key)
220 }
221
222 pub(crate) fn try_get_id(&self) -> anyhow::Result<&str> {
223 let id_val = self
224 .find_value("id")
225 .ok_or_else(|| anyhow!("no id field present in the config"))?;
226 if let toml::Value::String(id) = id_val {
227 Ok(id)
228 } else {
229 bail!("no id field present in the config")
230 }
231 }
232
233 pub(crate) fn try_get_credentials_store(&self) -> anyhow::Result<PathBuf> {
234 let id_val = self
235 .find_value("credentials_database_path")
236 .ok_or_else(|| anyhow!("no 'credentials_database_path' field present in the config"))?;
237 if let toml::Value::String(credentials_store) = id_val {
238 Ok(credentials_store.parse()?)
239 } else {
240 bail!("no 'credentials_database_path' field present in the config")
241 }
242 }
243
244 pub(crate) fn try_get_private_id_key(&self) -> anyhow::Result<PathBuf> {
245 let id_val = self
246 .find_value("keys.private_identity_key_file")
247 .ok_or_else(|| {
248 anyhow!("no 'keys.private_identity_key_file' field present in the config")
249 })?;
250 if let toml::Value::String(pub_id_key) = id_val {
251 Ok(pub_id_key.parse()?)
252 } else {
253 bail!("no 'keys.private_identity_key_file' field present in the config")
254 }
255 }
256}