feat: multiple ln backends

This commit is contained in:
thesimplekid
2024-07-07 19:01:18 +01:00
parent 242fffad65
commit 8d0b8fb357
3 changed files with 77 additions and 20 deletions

View File

@@ -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 }
}
}

View File

@@ -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())
}

View File

@@ -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)