Skip to main content

gateway_cli/
ecash_commands.rs

1use bitcoin::Address;
2use bitcoin::address::NetworkUnchecked;
3use clap::Subcommand;
4use fedimint_core::config::FederationId;
5use fedimint_core::util::SafeUrl;
6use fedimint_core::{Amount, BitcoinAmountOrAll};
7use fedimint_gateway_client::{
8    backup, get_deposit_address, pegin_from_onchain, receive_ecash, recheck_address, spend_ecash,
9    withdraw, withdraw_to_onchain,
10};
11use fedimint_gateway_common::{
12    BackupPayload, DepositAddressPayload, DepositAddressRecheckPayload, PeginFromOnchainPayload,
13    ReceiveEcashPayload, SpendEcashPayload, WithdrawPayload, WithdrawToOnchainPayload,
14};
15use fedimint_ln_common::client::GatewayApi;
16
17use crate::{CliOutput, CliOutputResult};
18
19/// Ecash management commands for pegging funds into a federation, pegging funds
20/// out of a federation, or spending/receiving ecash.
21#[derive(Subcommand)]
22pub enum EcashCommands {
23    /// Make a backup of snapshot of all e-cash.
24    Backup {
25        #[clap(long)]
26        federation_id: FederationId,
27    },
28    /// Generate a new peg-in address to a federation that the gateway can claim
29    /// e-cash for later.
30    Pegin {
31        #[clap(long)]
32        federation_id: FederationId,
33    },
34    /// Trigger a recheck for deposits on a deposit address
35    PeginRecheck {
36        #[clap(long)]
37        address: bitcoin::Address<NetworkUnchecked>,
38        #[clap(long)]
39        federation_id: FederationId,
40    },
41    /// Send funds from the gateway's onchain wallet to the federation's ecash
42    /// wallet
43    PeginFromOnchain {
44        #[clap(long)]
45        federation_id: FederationId,
46        /// The amount to pegin
47        #[clap(long)]
48        amount: BitcoinAmountOrAll,
49        /// The fee rate to use in satoshis per vbyte.
50        #[clap(long)]
51        fee_rate_sats_per_vbyte: u64,
52    },
53    /// Claim funds from a gateway federation to an on-chain address.
54    Pegout {
55        #[clap(long)]
56        federation_id: FederationId,
57        /// The amount to withdraw
58        #[clap(long)]
59        amount: BitcoinAmountOrAll,
60        /// The address to send the funds to
61        #[clap(long)]
62        address: Address<NetworkUnchecked>,
63    },
64    /// Claim funds from a gateway federation to the gateway's onchain wallet
65    PegoutToOnchain {
66        #[clap(long)]
67        federation_id: FederationId,
68        /// The amount to withdraw
69        #[clap(long)]
70        amount: BitcoinAmountOrAll,
71    },
72    /// Send e-cash out of band
73    Send {
74        #[clap(long)]
75        federation_id: FederationId,
76        amount: Amount,
77    },
78    /// Receive e-cash out of band
79    Receive {
80        /// E-cash notes (`OOBNotes` for v1 or `ECash` for v2)
81        #[clap(long)]
82        notes: String,
83    },
84}
85
86impl EcashCommands {
87    pub async fn handle(self, client: &GatewayApi, base_url: &SafeUrl) -> CliOutputResult {
88        match self {
89            Self::Backup { federation_id } => {
90                backup(client, base_url, BackupPayload { federation_id }).await?;
91                Ok(CliOutput::Empty)
92            }
93            Self::Pegin { federation_id } => {
94                let address =
95                    get_deposit_address(client, base_url, DepositAddressPayload { federation_id })
96                        .await?;
97
98                Ok(CliOutput::DepositAddress { address })
99            }
100            Self::PeginRecheck {
101                address,
102                federation_id,
103            } => {
104                let response = recheck_address(
105                    client,
106                    base_url,
107                    DepositAddressRecheckPayload {
108                        address,
109                        federation_id,
110                    },
111                )
112                .await?;
113                Ok(CliOutput::DepositRecheck(response))
114            }
115            Self::PeginFromOnchain {
116                federation_id,
117                amount,
118                fee_rate_sats_per_vbyte,
119            } => {
120                let txid = pegin_from_onchain(
121                    client,
122                    base_url,
123                    PeginFromOnchainPayload {
124                        federation_id,
125                        amount,
126                        fee_rate_sats_per_vbyte,
127                    },
128                )
129                .await?;
130
131                Ok(CliOutput::PeginTxid { txid })
132            }
133            Self::Pegout {
134                federation_id,
135                amount,
136                address,
137            } => {
138                let response = withdraw(
139                    client,
140                    base_url,
141                    WithdrawPayload {
142                        federation_id,
143                        amount,
144                        address,
145                        quoted_fees: None,
146                    },
147                )
148                .await?;
149
150                Ok(CliOutput::Withdraw(response))
151            }
152            Self::PegoutToOnchain {
153                federation_id,
154                amount,
155            } => {
156                let response = withdraw_to_onchain(
157                    client,
158                    base_url,
159                    WithdrawToOnchainPayload {
160                        federation_id,
161                        amount,
162                    },
163                )
164                .await?;
165
166                Ok(CliOutput::Withdraw(response))
167            }
168            Self::Send {
169                federation_id,
170                amount,
171            } => {
172                let response = spend_ecash(
173                    client,
174                    base_url,
175                    SpendEcashPayload {
176                        federation_id,
177                        amount,
178                    },
179                )
180                .await?;
181
182                Ok(CliOutput::SpendEcash(response))
183            }
184            Self::Receive { notes } => {
185                let response =
186                    receive_ecash(client, base_url, ReceiveEcashPayload { notes }).await?;
187                Ok(CliOutput::ReceiveEcash(response))
188            }
189        }
190    }
191}