fedimint_meta_client/
cli.rs
1use std::str::FromStr as _;
2use std::{ffi, iter};
3
4use anyhow::Context as _;
5use clap::Parser;
6use fedimint_meta_common::{DEFAULT_META_KEY, MetaConsensusValue, MetaKey, MetaValue};
7use serde::Serialize;
8use serde_json::json;
9
10use super::MetaClientModule;
11use crate::api::MetaFederationApi;
12
13#[derive(Parser, Serialize)]
14enum Opts {
15 Get {
17 #[arg(long, default_value_t = DEFAULT_META_KEY)]
18 key: MetaKey,
19 #[arg(long)]
20 hex: bool,
21 },
22 GetRev {
24 #[arg(long, default_value_t = DEFAULT_META_KEY)]
25 key: MetaKey,
26 },
27 GetSubmissions {
29 #[arg(long, default_value_t = DEFAULT_META_KEY)]
30 key: MetaKey,
31 #[arg(long)]
32 hex: bool,
33 },
34 Submit {
36 #[arg(long, default_value_t = DEFAULT_META_KEY)]
37 key: MetaKey,
38 value: String,
39 #[arg(long)]
40 hex: bool,
41 },
42}
43
44pub(crate) async fn handle_cli_command(
45 meta: &MetaClientModule,
46 args: &[ffi::OsString],
47) -> anyhow::Result<serde_json::Value> {
48 let opts = Opts::parse_from(iter::once(&ffi::OsString::from("meta")).chain(args.iter()));
49
50 let res = match opts {
51 Opts::Get { key, hex } => match meta.module_api.get_consensus(key).await? {
52 Some(MetaConsensusValue { revision, value }) => {
53 let value = if hex {
54 serde_json::to_value(value).expect("can't fail")
55 } else {
56 value
57 .to_json_lossy()
58 .context("deserializing consensus value as json")?
59 };
60 json!({
61 "revision": revision,
62 "value": value
63 })
64 }
65 _ => serde_json::Value::Null,
66 },
67 Opts::GetRev { key } => match meta.module_api.get_consensus_rev(key).await? {
68 Some(rev) => {
69 json!({
70 "revision": rev,
71 })
72 }
73 _ => serde_json::Value::Null,
74 },
75 Opts::GetSubmissions { key, hex } => {
76 let submissions = meta
77 .module_api
78 .get_submissions(key, meta.admin_auth()?)
79 .await?;
80 let submissions: serde_json::Map<String, serde_json::Value> = submissions
81 .into_iter()
82 .map(|(peer_id, value)| -> anyhow::Result<_> {
83 let value = if hex {
84 serde_json::Value::String(value.to_string())
85 } else {
86 serde_json::from_reader(value.as_slice())
87 .context("deserializing submission value")?
88 };
89
90 Ok((peer_id.to_string(), value))
91 })
92 .collect::<anyhow::Result<_, _>>()?;
93
94 serde_json::Value::Object(submissions)
95 }
96 Opts::Submit { key, value, hex } => {
97 let value: MetaValue = if hex {
98 MetaValue::from_str(&value).context("value not a valid hex string")?
99 } else {
100 let _valid_json: serde_json::Value =
101 serde_json::from_str(&value).context("value not a valid json string")?;
102 MetaValue::from(value.as_bytes())
103 };
104
105 meta.module_api
106 .submit(key, value, meta.admin_auth()?)
107 .await?;
108
109 serde_json::Value::Bool(true)
110 }
111 };
112
113 Ok(res)
114}