Quellcode durchsuchen

feat: multiple ln backends

thesimplekid vor 8 Monaten
Ursprung
Commit
8d0b8fb357
3 geänderte Dateien mit 77 neuen und 20 gelöschten Zeilen
  1. 20 2
      crates/cdk-axum/src/lib.rs
  2. 46 15
      crates/cdk-axum/src/router_handlers.rs
  3. 11 3
      crates/cdk-mintd/src/main.rs

+ 20 - 2
crates/cdk-axum/src/lib.rs

@@ -3,6 +3,7 @@
 #![warn(missing_docs)]
 #![warn(rustdoc::bare_urls)]
 
+use std::collections::HashMap;
 use std::sync::Arc;
 
 use anyhow::Result;
@@ -10,6 +11,7 @@ use axum::routing::{get, post};
 use axum::Router;
 use cdk::cdk_lightning::{self, MintLightning};
 use cdk::mint::Mint;
+use cdk::nuts::{CurrencyUnit, PaymentMethod};
 use router_handlers::*;
 
 mod router_handlers;
@@ -18,7 +20,7 @@ mod router_handlers;
 pub async fn create_mint_router(
     mint_url: &str,
     mint: Arc<Mint>,
-    ln: Arc<dyn MintLightning<Err = cdk_lightning::Error> + Send + Sync>,
+    ln: HashMap<LnKey, Arc<dyn MintLightning<Err = cdk_lightning::Error> + Send + Sync>>,
     quote_ttl: u64,
 ) -> Result<Router> {
     let state = MintState {
@@ -56,8 +58,24 @@ pub async fn create_mint_router(
 
 #[derive(Clone)]
 struct MintState {
-    ln: Arc<dyn MintLightning<Err = cdk_lightning::Error> + Send + Sync>,
+    ln: HashMap<LnKey, Arc<dyn MintLightning<Err = cdk_lightning::Error> + Send + Sync>>,
     mint: Arc<Mint>,
     mint_url: String,
     quote_ttl: u64,
 }
+
+/// Key used in hashmap of ln backends to identify what unit and payment method it is for
+#[derive(Debug, Clone, Hash, PartialEq, Eq)]
+pub struct LnKey {
+    /// Unit of Payment backend
+    pub unit: CurrencyUnit,
+    /// Method of payment backend
+    pub method: PaymentMethod,
+}
+
+impl LnKey {
+    /// Create new [`LnKey`]
+    pub fn new(unit: CurrencyUnit, method: PaymentMethod) -> Self {
+        Self { unit, method }
+    }
+}

+ 46 - 15
crates/cdk-axum/src/router_handlers.rs

@@ -11,12 +11,12 @@ use cdk::nuts::{
     CheckStateRequest, CheckStateResponse, CurrencyUnit, Id, KeysResponse, KeysetResponse,
     MeltBolt11Request, MeltQuoteBolt11Request, MeltQuoteBolt11Response, MintBolt11Request,
     MintBolt11Response, MintInfo, MintQuoteBolt11Request, MintQuoteBolt11Response, MintQuoteState,
-    RestoreRequest, RestoreResponse, SwapRequest, SwapResponse,
+    PaymentMethod, RestoreRequest, RestoreResponse, SwapRequest, SwapResponse,
 };
 use cdk::util::unix_time;
 use cdk::Bolt11Invoice;
 
-use crate::MintState;
+use crate::{LnKey, MintState};
 
 pub async fn get_keys(State(state): State<MintState>) -> Result<Json<KeysResponse>, Response> {
     let pubkeys = state.mint.pubkeys().await.map_err(|err| {
@@ -52,16 +52,23 @@ pub async fn get_mint_bolt11_quote(
     State(state): State<MintState>,
     Json(payload): Json<MintQuoteBolt11Request>,
 ) -> Result<Json<MintQuoteBolt11Response>, Response> {
-    let amount =
-        to_unit(payload.amount, &payload.unit, &state.ln.get_base_unit()).map_err(|err| {
-            tracing::error!("Backed does not support unit: {}", err);
+    let ln = state
+        .ln
+        .get(&LnKey::new(payload.unit, PaymentMethod::Bolt11))
+        .ok_or({
+            tracing::info!("Bolt11 mint request for unsupported unit");
+
             into_response(Error::UnsupportedUnit)
         })?;
 
+    let amount = to_unit(payload.amount, &payload.unit, &ln.get_base_unit()).map_err(|err| {
+        tracing::error!("Backed does not support unit: {}", err);
+        into_response(Error::UnsupportedUnit)
+    })?;
+
     let quote_expiry = unix_time() + state.quote_ttl;
 
-    let create_invoice_response = state
-        .ln
+    let create_invoice_response = ln
         .create_invoice(amount, "".to_string(), quote_expiry)
         .await
         .map_err(|err| {
@@ -124,6 +131,15 @@ pub async fn get_melt_bolt11_quote(
     State(state): State<MintState>,
     Json(payload): Json<MeltQuoteBolt11Request>,
 ) -> Result<Json<MeltQuoteBolt11Response>, Response> {
+    let ln = state
+        .ln
+        .get(&LnKey::new(payload.unit, PaymentMethod::Bolt11))
+        .ok_or({
+            tracing::info!("Could not get ln backend for {}, bolt11 ", payload.unit);
+
+            into_response(Error::UnsupportedUnit)
+        })?;
+
     let invoice_amount_msat = payload
         .request
         .amount_milli_satoshis()
@@ -137,7 +153,15 @@ pub async fn get_melt_bolt11_quote(
             into_response(Error::UnsupportedUnit)
         })?;
 
-    let payment_quote = state.ln.get_payment_quote(&payload).await.unwrap();
+    let payment_quote = ln.get_payment_quote(&payload).await.map_err(|err| {
+        tracing::error!(
+            "Could not get payment quote for mint quote, {} bolt11, {}",
+            payload.unit,
+            err
+        );
+
+        into_response(Error::UnsupportedUnit)
+    })?;
 
     let quote = state
         .mint
@@ -314,8 +338,19 @@ pub async fn post_melt_bolt11(
                 }
             }
 
-            let pre = match state
+            let ln = state
                 .ln
+                .get(&LnKey::new(quote.unit, PaymentMethod::Bolt11))
+                .ok_or({
+                    tracing::info!("Could not get ln backend for {}, bolt11 ", quote.unit);
+                    if let Err(err) = state.mint.process_unpaid_melt(&payload).await {
+                        tracing::error!("Could not reset melt quote state: {}", err);
+                    }
+
+                    into_response(Error::UnsupportedUnit)
+                })?;
+
+            let pre = match ln
                 .pay_invoice(quote.clone(), partial_msats, max_fee_msats)
                 .await
             {
@@ -335,12 +370,8 @@ pub async fn post_melt_bolt11(
                 }
             };
 
-            let amount_spent = to_unit(
-                pre.total_spent_msats,
-                &state.ln.get_base_unit(),
-                &quote.unit,
-            )
-            .map_err(|_| into_response(Error::UnsupportedUnit))?;
+            let amount_spent = to_unit(pre.total_spent_msats, &ln.get_base_unit(), &quote.unit)
+                .map_err(|_| into_response(Error::UnsupportedUnit))?;
 
             (pre.payment_preimage, amount_spent.into())
         }

+ 11 - 3
crates/cdk-mintd/src/main.rs

@@ -3,6 +3,7 @@
 #![warn(missing_docs)]
 #![warn(rustdoc::bare_urls)]
 
+use std::collections::HashMap;
 use std::path::PathBuf;
 use std::str::FromStr;
 use std::sync::Arc;
@@ -14,7 +15,8 @@ use cdk::cdk_database::{self, MintDatabase};
 use cdk::cdk_lightning;
 use cdk::cdk_lightning::MintLightning;
 use cdk::mint::{FeeReserve, Mint};
-use cdk::nuts::{ContactInfo, MintInfo, MintVersion, Nuts};
+use cdk::nuts::{ContactInfo, CurrencyUnit, MintInfo, MintVersion, Nuts, PaymentMethod};
+use cdk_axum::LnKey;
 use cdk_cln::Cln;
 use cdk_redb::MintRedbDatabase;
 use cdk_sqlite::MintSqliteDatabase;
@@ -164,9 +166,15 @@ async fn main() -> anyhow::Result<()> {
         .seconds_quote_is_valid_for
         .unwrap_or(DEFAULT_QUOTE_TTL_SECS);
 
+    let mut ln_backends = HashMap::new();
+
+    ln_backends.insert(
+        LnKey::new(CurrencyUnit::Sat, PaymentMethod::Bolt11),
+        Arc::clone(&ln),
+    );
+
     let v1_service =
-        cdk_axum::create_mint_router(&mint_url, Arc::clone(&mint), Arc::clone(&ln), quote_ttl)
-            .await?;
+        cdk_axum::create_mint_router(&mint_url, Arc::clone(&mint), ln_backends, quote_ttl).await?;
 
     let mint_service = Router::new()
         .nest("/", v1_service)