Skip to main content

fedimint_mintv2_client/
cli.rs

1use std::{ffi, iter};
2
3use clap::Parser;
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::{MintClientModule, ReceiveECashError, SendECashError};
11
12#[derive(Parser, Serialize)]
13enum Opts {
14    /// Count the `ECash` notes in the client's database by denomination.
15    Count,
16    /// Send `ECash` for the given amount.
17    Send {
18        amount: Amount,
19        /// Embed the federation's invite code in the serialized ecash so a
20        /// recipient that hasn't joined the federation can do so from it.
21        #[clap(long)]
22        include_invite: bool,
23    },
24    /// Receive the `ECash` by reissuing the notes and return the amount.
25    Receive { ecash: String },
26}
27
28pub(crate) async fn handle_cli_command(
29    mint: &MintClientModule,
30    args: &[ffi::OsString],
31) -> Result<Value, CliCommandError> {
32    let opts = Opts::parse_from(iter::once(&ffi::OsString::from("mintv2")).chain(args.iter()));
33
34    match opts {
35        Opts::Count => Ok(json(mint.get_count_by_denomination().await)),
36        Opts::Send {
37            amount,
38            include_invite,
39        } => {
40            let (_, ecash) = mint.send(amount, Value::Null, include_invite).await?;
41            let ecash = base32::encode_prefixed(FEDIMINT_PREFIX, &ecash);
42
43            Ok(json(ecash))
44        }
45        Opts::Receive { ecash } => {
46            let ecash = base32::decode_prefixed(FEDIMINT_PREFIX, &ecash)?;
47
48            let operation_id = mint.receive(ecash, Value::Null).await?;
49
50            let state = mint
51                .await_final_receive_operation_state(operation_id)
52                .await?;
53
54            Ok(json(state))
55        }
56    }
57}
58
59fn json<T: Serialize>(value: T) -> Value {
60    serde_json::to_value(value).expect("JSON serialization failed")
61}
62
63/// A failure of a `mintv2` module command.
64#[derive(Debug, thiserror::Error)]
65pub(crate) enum CliCommandError {
66    /// The e-cash could not be sent.
67    #[error(transparent)]
68    Send(#[from] SendECashError),
69
70    /// The e-cash string is not valid.
71    #[error(transparent)]
72    Decode(#[from] PrefixedDecodeError),
73
74    /// The e-cash could not be received.
75    #[error(transparent)]
76    Receive(#[from] ReceiveECashError),
77
78    /// The receive operation could not be looked up.
79    #[error(transparent)]
80    OperationLookup(#[from] OperationLookupError),
81}