mirror of
https://github.com/aljazceru/cdk.git
synced 2026-02-06 05:36:28 +01:00
feat: multiple ln backends
This commit is contained in:
@@ -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 }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(),
|
||||
"e.unit,
|
||||
)
|
||||
.map_err(|_| into_response(Error::UnsupportedUnit))?;
|
||||
let amount_spent = to_unit(pre.total_spent_msats, &ln.get_base_unit(), "e.unit)
|
||||
.map_err(|_| into_response(Error::UnsupportedUnit))?;
|
||||
|
||||
(pre.payment_preimage, amount_spent.into())
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user