ln_gateway/rpc/
mod.rs

1pub mod rpc_client;
2pub mod rpc_server;
3
4use std::collections::BTreeMap;
5use std::str::FromStr;
6
7use bitcoin::address::NetworkUnchecked;
8use bitcoin::{Address, Network};
9use fedimint_core::config::{FederationId, JsonClientConfig};
10use fedimint_core::core::OperationId;
11use fedimint_core::{secp256k1, Amount, BitcoinAmountOrAll};
12use fedimint_ln_common::config::parse_routing_fees;
13use fedimint_mint_client::OOBNotes;
14use fedimint_wallet_client::PegOutFees;
15use lightning_invoice::{Bolt11Invoice, RoutingFees};
16use serde::{Deserialize, Serialize};
17
18use crate::lightning::LightningMode;
19use crate::SafeUrl;
20
21pub const V1_API_ENDPOINT: &str = "v1";
22
23pub const ADDRESS_ENDPOINT: &str = "/address";
24pub const BACKUP_ENDPOINT: &str = "/backup";
25pub const CONFIGURATION_ENDPOINT: &str = "/config";
26pub const CONNECT_FED_ENDPOINT: &str = "/connect_fed";
27pub const CREATE_BOLT11_INVOICE_FOR_OPERATOR_ENDPOINT: &str = "/create_bolt11_invoice_for_operator";
28pub const GATEWAY_INFO_ENDPOINT: &str = "/info";
29pub const GET_BALANCES_ENDPOINT: &str = "/balances";
30pub const GATEWAY_INFO_POST_ENDPOINT: &str = "/info";
31pub const GET_LN_ONCHAIN_ADDRESS_ENDPOINT: &str = "/get_ln_onchain_address";
32pub const LEAVE_FED_ENDPOINT: &str = "/leave_fed";
33pub const LIST_ACTIVE_CHANNELS_ENDPOINT: &str = "/list_active_channels";
34pub const MNEMONIC_ENDPOINT: &str = "/mnemonic";
35pub const OPEN_CHANNEL_ENDPOINT: &str = "/open_channel";
36pub const CLOSE_CHANNELS_WITH_PEER_ENDPOINT: &str = "/close_channels_with_peer";
37pub const PAY_INVOICE_FOR_OPERATOR_ENDPOINT: &str = "/pay_invoice_for_operator";
38pub const RECEIVE_ECASH_ENDPOINT: &str = "/receive_ecash";
39pub const SET_CONFIGURATION_ENDPOINT: &str = "/set_configuration";
40pub const STOP_ENDPOINT: &str = "/stop";
41pub const SEND_ONCHAIN_ENDPOINT: &str = "/send_onchain";
42pub const SPEND_ECASH_ENDPOINT: &str = "/spend_ecash";
43pub const WITHDRAW_ENDPOINT: &str = "/withdraw";
44
45#[derive(Debug, Serialize, Deserialize, Clone)]
46pub struct ConnectFedPayload {
47    pub invite_code: String,
48    #[serde(default)]
49    #[cfg(feature = "tor")]
50    pub use_tor: Option<bool>,
51    pub recover: Option<bool>,
52}
53
54#[derive(Debug, Serialize, Deserialize, Clone)]
55pub struct LeaveFedPayload {
56    pub federation_id: FederationId,
57}
58
59#[derive(Debug, Serialize, Deserialize)]
60pub struct InfoPayload;
61
62#[derive(Debug, Serialize, Deserialize)]
63pub struct BackupPayload {
64    pub federation_id: FederationId,
65}
66
67#[derive(Debug, Serialize, Deserialize, Clone)]
68pub struct ConfigPayload {
69    pub federation_id: Option<FederationId>,
70}
71
72#[derive(Debug, Serialize, Deserialize, Clone)]
73pub struct DepositAddressPayload {
74    pub federation_id: FederationId,
75}
76
77#[derive(Debug, Serialize, Deserialize, Clone)]
78pub struct WithdrawPayload {
79    pub federation_id: FederationId,
80    pub amount: BitcoinAmountOrAll,
81    pub address: Address<NetworkUnchecked>,
82}
83
84#[derive(Debug, Serialize, Deserialize, Clone)]
85pub struct WithdrawResponse {
86    pub txid: bitcoin::Txid,
87    pub fees: PegOutFees,
88}
89
90/// Information about one of the feds we are connected to
91#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
92pub struct FederationInfo {
93    pub federation_id: FederationId,
94    pub federation_name: Option<String>,
95    pub balance_msat: Amount,
96    pub federation_index: u64,
97    pub routing_fees: Option<FederationRoutingFees>,
98}
99
100#[derive(Debug, Serialize, Deserialize, PartialEq)]
101pub struct GatewayInfo {
102    pub version_hash: String,
103    pub federations: Vec<FederationInfo>,
104    /// Mapping from short channel id to the federation id that it belongs to.
105    // TODO: Remove this alias once it no longer breaks backwards compatibility.
106    #[serde(alias = "channels")]
107    pub federation_fake_scids: Option<BTreeMap<u64, FederationId>>,
108    pub lightning_pub_key: Option<String>,
109    pub lightning_alias: Option<String>,
110    pub gateway_id: secp256k1::PublicKey,
111    pub gateway_state: String,
112    pub network: Option<Network>,
113    // TODO: This is here to allow for backwards compatibility with old versions of this struct. We
114    // should be able to remove it once 0.4.0 is released.
115    #[serde(default)]
116    pub block_height: Option<u32>,
117    // TODO: This is here to allow for backwards compatibility with old versions of this struct. We
118    // should be able to remove it once 0.4.0 is released.
119    #[serde(default)]
120    pub synced_to_chain: bool,
121    pub api: SafeUrl,
122    pub lightning_mode: Option<LightningMode>,
123}
124
125#[derive(Debug, Serialize, Deserialize, PartialEq)]
126pub struct GatewayFedConfig {
127    pub federations: BTreeMap<FederationId, JsonClientConfig>,
128}
129
130#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
131pub struct FederationRoutingFees {
132    pub base_msat: u32,
133    pub proportional_millionths: u32,
134}
135
136impl From<FederationRoutingFees> for RoutingFees {
137    fn from(value: FederationRoutingFees) -> Self {
138        RoutingFees {
139            base_msat: value.base_msat,
140            proportional_millionths: value.proportional_millionths,
141        }
142    }
143}
144
145impl From<RoutingFees> for FederationRoutingFees {
146    fn from(value: RoutingFees) -> Self {
147        FederationRoutingFees {
148            base_msat: value.base_msat,
149            proportional_millionths: value.proportional_millionths,
150        }
151    }
152}
153
154impl FromStr for FederationRoutingFees {
155    type Err = anyhow::Error;
156
157    fn from_str(s: &str) -> Result<Self, Self::Err> {
158        let routing_fees = parse_routing_fees(s)?;
159        Ok(FederationRoutingFees {
160            base_msat: routing_fees.base_msat,
161            proportional_millionths: routing_fees.proportional_millionths,
162        })
163    }
164}
165
166#[derive(Debug, Serialize, Deserialize, Clone)]
167pub struct SetConfigurationPayload {
168    pub password: Option<String>,
169    pub num_route_hints: Option<u32>,
170    pub routing_fees: Option<FederationRoutingFees>,
171    pub network: Option<Network>,
172    pub per_federation_routing_fees: Option<Vec<(FederationId, FederationRoutingFees)>>,
173}
174
175#[derive(Debug, Serialize, Deserialize, Clone)]
176pub struct CreateInvoiceForOperatorPayload {
177    pub amount_msats: u64,
178    pub expiry_secs: Option<u32>,
179    pub description: Option<String>,
180}
181
182#[derive(Debug, Serialize, Deserialize, Clone)]
183pub struct PayInvoiceForOperatorPayload {
184    pub invoice: Bolt11Invoice,
185}
186
187#[derive(Debug, Serialize, Deserialize, Clone)]
188pub struct OpenChannelPayload {
189    pub pubkey: secp256k1::PublicKey,
190    pub host: String,
191    pub channel_size_sats: u64,
192    pub push_amount_sats: u64,
193}
194
195#[derive(Debug, Serialize, Deserialize, Clone)]
196pub struct CloseChannelsWithPeerPayload {
197    pub pubkey: secp256k1::PublicKey,
198}
199
200#[derive(Debug, Serialize, Deserialize, Clone)]
201pub struct SendOnchainPayload {
202    pub address: Address<NetworkUnchecked>,
203    pub amount: BitcoinAmountOrAll,
204    pub fee_rate_sats_per_vbyte: u64,
205}
206
207#[derive(Debug, Serialize, Deserialize, Clone)]
208pub struct SpendEcashPayload {
209    /// Federation id of the e-cash to spend
210    pub federation_id: FederationId,
211    /// The amount of e-cash to spend
212    pub amount: Amount,
213    /// If the exact amount cannot be represented, return e-cash of a higher
214    /// value instead of failing
215    #[serde(default)]
216    pub allow_overpay: bool,
217    /// After how many seconds we will try to reclaim the e-cash if it
218    /// hasn't been redeemed by the recipient. Defaults to one week.
219    #[serde(default = "default_timeout")]
220    pub timeout: u64,
221    /// If the necessary information to join the federation the e-cash
222    /// belongs to should be included in the serialized notes
223    #[serde(default)]
224    pub include_invite: bool,
225}
226
227/// Default timeout for e-cash redemption of one week in seconds
228fn default_timeout() -> u64 {
229    604_800
230}
231
232#[derive(Debug, Serialize, Deserialize, Clone)]
233pub struct SpendEcashResponse {
234    pub operation_id: OperationId,
235    pub notes: OOBNotes,
236}
237
238#[derive(Debug, Serialize, Deserialize, Clone)]
239pub struct ReceiveEcashPayload {
240    pub notes: OOBNotes,
241    #[serde(default)]
242    pub wait: bool,
243}
244
245#[derive(Debug, Serialize, Deserialize, Clone)]
246pub struct ReceiveEcashResponse {
247    pub amount: Amount,
248}
249
250#[derive(serde::Serialize, serde::Deserialize)]
251pub struct GatewayBalances {
252    pub onchain_balance_sats: u64,
253    pub lightning_balance_msats: u64,
254    pub ecash_balances: Vec<FederationBalanceInfo>,
255    pub inbound_lightning_liquidity_msats: u64,
256}
257
258#[derive(serde::Serialize, serde::Deserialize)]
259pub struct FederationBalanceInfo {
260    pub federation_id: FederationId,
261    pub ecash_balance_msats: Amount,
262}
263
264#[derive(Debug, Serialize, Deserialize, Clone)]
265pub struct MnemonicResponse {
266    pub mnemonic: Vec<String>,
267
268    // Legacy federations are federations that the gateway joined prior to v0.5.0
269    // and do not derive their secrets from the gateway's mnemonic. They also use
270    // a separate database from the gateway's db.
271    pub legacy_federations: Vec<FederationId>,
272}