fedimint_mint_client/
cli.rs

1use std::{ffi, iter};
2
3use anyhow::bail;
4use clap::Parser;
5use futures::StreamExt;
6use serde::Serialize;
7use serde_json::json;
8
9use crate::{MintClientModule, OOBNotes, ReissueExternalNotesState};
10
11#[derive(Parser, Serialize)]
12enum Opts {
13    /// Reissue out of band notes
14    Reissue { notes: OOBNotes },
15    /// Verifies the signatures of e-cash notes, if the online flag is specified
16    /// it also checks with the mint if the notes were already spent
17    Validate {
18        /// Whether to check with the mint if the notes were already spent
19        /// (CAUTION: this hurts privacy)
20        #[clap(long)]
21        online: bool,
22        /// E-Cash note to validate
23        oob_notes: OOBNotes,
24    },
25}
26
27pub(crate) async fn handle_cli_command(
28    mint: &MintClientModule,
29    args: &[ffi::OsString],
30) -> anyhow::Result<serde_json::Value> {
31    let opts = Opts::parse_from(iter::once(&ffi::OsString::from("mint")).chain(args.iter()));
32
33    match opts {
34        Opts::Reissue { notes } => {
35            let amount = notes.total_amount();
36
37            let operation_id = mint.reissue_external_notes(notes, ()).await?;
38
39            let mut updates = mint
40                .subscribe_reissue_external_notes(operation_id)
41                .await
42                .unwrap()
43                .into_stream();
44
45            while let Some(update) = updates.next().await {
46                if let ReissueExternalNotesState::Failed(e) = update {
47                    bail!("Reissue failed: {e}");
48                }
49            }
50
51            Ok(serde_json::to_value(amount).expect("JSON serialization failed"))
52        }
53        Opts::Validate { oob_notes, online } => {
54            let amount = mint.validate_notes(&oob_notes)?;
55
56            if online {
57                let any_spent = mint.check_note_spent(&oob_notes).await?;
58                Ok(json!({
59                    "any_spent": any_spent,
60                    "amount_msat": amount,
61                }))
62            } else {
63                Ok(json!({
64                    "amount_msat": amount,
65                }))
66            }
67        }
68    }
69}