fedimint_mintv2_client/
cli.rs1use std::{ffi, iter};
2
3use clap::{Parser, Subcommand};
4use fedimint_client_module::error::OperationLookupError;
5use fedimint_core::Amount;
6use fedimint_core::base32::{self, FEDIMINT_PREFIX, PrefixedDecodeError};
7use serde::Serialize;
8use serde_json::Value;
9
10use crate::{ECash, MintClientModule, ReceiveECashError, SendECashError, SpendableNote};
11
12#[derive(Parser, Serialize)]
13enum Opts {
14 Count,
16 Send {
18 amount: Amount,
19 #[clap(long)]
22 include_invite: bool,
23 },
24 Receive { ecash: String },
26 Dev {
28 #[clap(subcommand)]
29 command: DevOpts,
30 },
31}
32
33#[derive(Subcommand, Serialize)]
34enum DevOpts {
35 Decode { ecash: String },
38}
39
40pub(crate) async fn handle_cli_command(
41 mint: &MintClientModule,
42 args: &[ffi::OsString],
43) -> Result<Value, CliCommandError> {
44 let opts = Opts::parse_from(iter::once(&ffi::OsString::from("mintv2")).chain(args.iter()));
45
46 match opts {
47 Opts::Count => Ok(json(mint.get_count_by_denomination().await)),
48 Opts::Send {
49 amount,
50 include_invite,
51 } => {
52 let (_, ecash) = mint.send(amount, Value::Null, include_invite).await?;
53 let ecash = base32::encode_prefixed(FEDIMINT_PREFIX, &ecash);
54
55 Ok(json(ecash))
56 }
57 Opts::Receive { ecash } => {
58 let ecash = base32::decode_prefixed(FEDIMINT_PREFIX, &ecash)?;
59
60 let operation_id = mint.receive(ecash, Value::Null).await?;
61
62 let state = mint
63 .await_final_receive_operation_state(operation_id)
64 .await?;
65
66 Ok(json(state))
67 }
68 Opts::Dev {
69 command: DevOpts::Decode { ecash },
70 } => {
71 let ecash: ECash = base32::decode_prefixed(FEDIMINT_PREFIX, &ecash)?;
72 let notes = ecash.notes();
73
74 Ok(serde_json::json!({
75 "federation_id": ecash.mint(),
76 "unit": ecash.unit(),
77 "amount": ecash.amount(),
78 "note_count": notes.len(),
79 "notes": notes.iter().map(SpendableNote::note).collect::<Vec<_>>(),
80 "invite": ecash.federation_invite(),
81 }))
82 }
83 }
84}
85
86fn json<T: Serialize>(value: T) -> Value {
87 serde_json::to_value(value).expect("JSON serialization failed")
88}
89
90#[derive(Debug, thiserror::Error)]
92pub(crate) enum CliCommandError {
93 #[error(transparent)]
95 Send(#[from] SendECashError),
96
97 #[error(transparent)]
99 Decode(#[from] PrefixedDecodeError),
100
101 #[error(transparent)]
103 Receive(#[from] ReceiveECashError),
104
105 #[error(transparent)]
107 OperationLookup(#[from] OperationLookupError),
108}