mirror of
https://github.com/aljazceru/cdk.git
synced 2025-12-21 06:34:59 +01:00
feat: mintd use mint builder
This commit is contained in:
@@ -1,2 +1,2 @@
|
|||||||
[language-server.rust-analyzer.config]
|
[language-server.rust-analyzer.config]
|
||||||
cargo = { features = ["wallet", "mint"] }
|
cargo = { features = ["wallet", "mint", "swagger"] }
|
||||||
|
|||||||
@@ -16,10 +16,7 @@ use cdk::cdk_lightning::{
|
|||||||
self, CreateInvoiceResponse, MintLightning, PayInvoiceResponse, PaymentQuoteResponse, Settings,
|
self, CreateInvoiceResponse, MintLightning, PayInvoiceResponse, PaymentQuoteResponse, Settings,
|
||||||
};
|
};
|
||||||
use cdk::mint::FeeReserve;
|
use cdk::mint::FeeReserve;
|
||||||
use cdk::nuts::{
|
use cdk::nuts::{CurrencyUnit, MeltQuoteBolt11Request, MeltQuoteState, MintQuoteState};
|
||||||
CurrencyUnit, MeltMethodSettings, MeltQuoteBolt11Request, MeltQuoteState, MintMethodSettings,
|
|
||||||
MintQuoteState,
|
|
||||||
};
|
|
||||||
use cdk::util::{hex, unix_time};
|
use cdk::util::{hex, unix_time};
|
||||||
use cdk::{mint, Bolt11Invoice};
|
use cdk::{mint, Bolt11Invoice};
|
||||||
use cln_rpc::model::requests::{
|
use cln_rpc::model::requests::{
|
||||||
@@ -45,28 +42,19 @@ pub struct Cln {
|
|||||||
rpc_socket: PathBuf,
|
rpc_socket: PathBuf,
|
||||||
cln_client: Arc<Mutex<cln_rpc::ClnRpc>>,
|
cln_client: Arc<Mutex<cln_rpc::ClnRpc>>,
|
||||||
fee_reserve: FeeReserve,
|
fee_reserve: FeeReserve,
|
||||||
mint_settings: MintMethodSettings,
|
|
||||||
melt_settings: MeltMethodSettings,
|
|
||||||
wait_invoice_cancel_token: CancellationToken,
|
wait_invoice_cancel_token: CancellationToken,
|
||||||
wait_invoice_is_active: Arc<AtomicBool>,
|
wait_invoice_is_active: Arc<AtomicBool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Cln {
|
impl Cln {
|
||||||
/// Create new [`Cln`]
|
/// Create new [`Cln`]
|
||||||
pub async fn new(
|
pub async fn new(rpc_socket: PathBuf, fee_reserve: FeeReserve) -> Result<Self, Error> {
|
||||||
rpc_socket: PathBuf,
|
|
||||||
fee_reserve: FeeReserve,
|
|
||||||
mint_settings: MintMethodSettings,
|
|
||||||
melt_settings: MeltMethodSettings,
|
|
||||||
) -> Result<Self, Error> {
|
|
||||||
let cln_client = cln_rpc::ClnRpc::new(&rpc_socket).await?;
|
let cln_client = cln_rpc::ClnRpc::new(&rpc_socket).await?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
rpc_socket,
|
rpc_socket,
|
||||||
cln_client: Arc::new(Mutex::new(cln_client)),
|
cln_client: Arc::new(Mutex::new(cln_client)),
|
||||||
fee_reserve,
|
fee_reserve,
|
||||||
mint_settings,
|
|
||||||
melt_settings,
|
|
||||||
wait_invoice_cancel_token: CancellationToken::new(),
|
wait_invoice_cancel_token: CancellationToken::new(),
|
||||||
wait_invoice_is_active: Arc::new(AtomicBool::new(false)),
|
wait_invoice_is_active: Arc::new(AtomicBool::new(false)),
|
||||||
})
|
})
|
||||||
@@ -81,8 +69,6 @@ impl MintLightning for Cln {
|
|||||||
Settings {
|
Settings {
|
||||||
mpp: true,
|
mpp: true,
|
||||||
unit: CurrencyUnit::Msat,
|
unit: CurrencyUnit::Msat,
|
||||||
mint_settings: self.mint_settings.clone(),
|
|
||||||
melt_settings: self.melt_settings.clone(),
|
|
||||||
invoice_description: true,
|
invoice_description: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,10 +20,7 @@ use cdk::cdk_lightning::{
|
|||||||
};
|
};
|
||||||
use cdk::mint;
|
use cdk::mint;
|
||||||
use cdk::mint::FeeReserve;
|
use cdk::mint::FeeReserve;
|
||||||
use cdk::nuts::{
|
use cdk::nuts::{CurrencyUnit, MeltQuoteBolt11Request, MeltQuoteState, MintQuoteState};
|
||||||
CurrencyUnit, MeltMethodSettings, MeltQuoteBolt11Request, MeltQuoteState, MintMethodSettings,
|
|
||||||
MintQuoteState,
|
|
||||||
};
|
|
||||||
use cdk::util::unix_time;
|
use cdk::util::unix_time;
|
||||||
use error::Error;
|
use error::Error;
|
||||||
use futures::stream::StreamExt;
|
use futures::stream::StreamExt;
|
||||||
@@ -44,8 +41,6 @@ pub struct FakeWallet {
|
|||||||
fee_reserve: FeeReserve,
|
fee_reserve: FeeReserve,
|
||||||
sender: tokio::sync::mpsc::Sender<String>,
|
sender: tokio::sync::mpsc::Sender<String>,
|
||||||
receiver: Arc<Mutex<Option<tokio::sync::mpsc::Receiver<String>>>>,
|
receiver: Arc<Mutex<Option<tokio::sync::mpsc::Receiver<String>>>>,
|
||||||
mint_settings: MintMethodSettings,
|
|
||||||
melt_settings: MeltMethodSettings,
|
|
||||||
payment_states: Arc<Mutex<HashMap<String, MeltQuoteState>>>,
|
payment_states: Arc<Mutex<HashMap<String, MeltQuoteState>>>,
|
||||||
failed_payment_check: Arc<Mutex<HashSet<String>>>,
|
failed_payment_check: Arc<Mutex<HashSet<String>>>,
|
||||||
payment_delay: u64,
|
payment_delay: u64,
|
||||||
@@ -57,8 +52,6 @@ impl FakeWallet {
|
|||||||
/// Creat new [`FakeWallet`]
|
/// Creat new [`FakeWallet`]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
fee_reserve: FeeReserve,
|
fee_reserve: FeeReserve,
|
||||||
mint_settings: MintMethodSettings,
|
|
||||||
melt_settings: MeltMethodSettings,
|
|
||||||
payment_states: HashMap<String, MeltQuoteState>,
|
payment_states: HashMap<String, MeltQuoteState>,
|
||||||
fail_payment_check: HashSet<String>,
|
fail_payment_check: HashSet<String>,
|
||||||
payment_delay: u64,
|
payment_delay: u64,
|
||||||
@@ -69,8 +62,6 @@ impl FakeWallet {
|
|||||||
fee_reserve,
|
fee_reserve,
|
||||||
sender,
|
sender,
|
||||||
receiver: Arc::new(Mutex::new(Some(receiver))),
|
receiver: Arc::new(Mutex::new(Some(receiver))),
|
||||||
mint_settings,
|
|
||||||
melt_settings,
|
|
||||||
payment_states: Arc::new(Mutex::new(payment_states)),
|
payment_states: Arc::new(Mutex::new(payment_states)),
|
||||||
failed_payment_check: Arc::new(Mutex::new(fail_payment_check)),
|
failed_payment_check: Arc::new(Mutex::new(fail_payment_check)),
|
||||||
payment_delay,
|
payment_delay,
|
||||||
@@ -112,8 +103,6 @@ impl MintLightning for FakeWallet {
|
|||||||
Settings {
|
Settings {
|
||||||
mpp: true,
|
mpp: true,
|
||||||
unit: CurrencyUnit::Msat,
|
unit: CurrencyUnit::Msat,
|
||||||
mint_settings: self.mint_settings.clone(),
|
|
||||||
melt_settings: self.melt_settings.clone(),
|
|
||||||
invoice_description: true,
|
invoice_description: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use cdk::{
|
|||||||
cdk_database::{self, MintDatabase},
|
cdk_database::{self, MintDatabase},
|
||||||
cdk_lightning::MintLightning,
|
cdk_lightning::MintLightning,
|
||||||
mint::FeeReserve,
|
mint::FeeReserve,
|
||||||
nuts::{CurrencyUnit, MeltMethodSettings, MintMethodSettings},
|
nuts::CurrencyUnit,
|
||||||
types::LnKey,
|
types::LnKey,
|
||||||
};
|
};
|
||||||
use cdk_fake_wallet::FakeWallet;
|
use cdk_fake_wallet::FakeWallet;
|
||||||
@@ -46,14 +46,7 @@ where
|
|||||||
percent_fee_reserve: 1.0,
|
percent_fee_reserve: 1.0,
|
||||||
};
|
};
|
||||||
|
|
||||||
let fake_wallet = FakeWallet::new(
|
let fake_wallet = FakeWallet::new(fee_reserve, HashMap::default(), HashSet::default(), 0);
|
||||||
fee_reserve,
|
|
||||||
MintMethodSettings::default(),
|
|
||||||
MeltMethodSettings::default(),
|
|
||||||
HashMap::default(),
|
|
||||||
HashSet::default(),
|
|
||||||
0,
|
|
||||||
);
|
|
||||||
|
|
||||||
ln_backends.insert(
|
ln_backends.insert(
|
||||||
LnKey::new(CurrencyUnit::Sat, cdk::nuts::PaymentMethod::Bolt11),
|
LnKey::new(CurrencyUnit::Sat, cdk::nuts::PaymentMethod::Bolt11),
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use cdk::{
|
|||||||
cdk_database::{self, MintDatabase},
|
cdk_database::{self, MintDatabase},
|
||||||
cdk_lightning::MintLightning,
|
cdk_lightning::MintLightning,
|
||||||
mint::{FeeReserve, Mint},
|
mint::{FeeReserve, Mint},
|
||||||
nuts::{CurrencyUnit, MeltMethodSettings, MintInfo, MintMethodSettings},
|
nuts::{CurrencyUnit, MintInfo},
|
||||||
types::{LnKey, QuoteTTL},
|
types::{LnKey, QuoteTTL},
|
||||||
};
|
};
|
||||||
use cdk_cln::Cln as CdkCln;
|
use cdk_cln::Cln as CdkCln;
|
||||||
@@ -131,13 +131,7 @@ pub async fn create_cln_backend(cln_client: &ClnClient) -> Result<CdkCln> {
|
|||||||
percent_fee_reserve: 1.0,
|
percent_fee_reserve: 1.0,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(CdkCln::new(
|
Ok(CdkCln::new(rpc_path, fee_reserve).await?)
|
||||||
rpc_path,
|
|
||||||
fee_reserve,
|
|
||||||
MintMethodSettings::default(),
|
|
||||||
MeltMethodSettings::default(),
|
|
||||||
)
|
|
||||||
.await?)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn create_mint<D>(
|
pub async fn create_mint<D>(
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ use cdk::cdk_lightning::MintLightning;
|
|||||||
use cdk::dhke::construct_proofs;
|
use cdk::dhke::construct_proofs;
|
||||||
use cdk::mint::FeeReserve;
|
use cdk::mint::FeeReserve;
|
||||||
use cdk::nuts::{
|
use cdk::nuts::{
|
||||||
CurrencyUnit, Id, KeySet, MeltMethodSettings, MintBolt11Request, MintInfo, MintMethodSettings,
|
CurrencyUnit, Id, KeySet, MintBolt11Request, MintInfo, MintQuoteBolt11Request, MintQuoteState,
|
||||||
MintQuoteBolt11Request, MintQuoteState, Nuts, PaymentMethod, PreMintSecrets, Proofs, State,
|
Nuts, PaymentMethod, PreMintSecrets, Proofs, State,
|
||||||
};
|
};
|
||||||
use cdk::types::{LnKey, QuoteTTL};
|
use cdk::types::{LnKey, QuoteTTL};
|
||||||
use cdk::wallet::client::{HttpClient, HttpClientMethods};
|
use cdk::wallet::client::{HttpClient, HttpClientMethods};
|
||||||
@@ -40,8 +40,6 @@ pub fn create_backends_fake_wallet(
|
|||||||
|
|
||||||
let wallet = Arc::new(FakeWallet::new(
|
let wallet = Arc::new(FakeWallet::new(
|
||||||
fee_reserve.clone(),
|
fee_reserve.clone(),
|
||||||
MintMethodSettings::default(),
|
|
||||||
MeltMethodSettings::default(),
|
|
||||||
HashMap::default(),
|
HashMap::default(),
|
||||||
HashSet::default(),
|
HashSet::default(),
|
||||||
0,
|
0,
|
||||||
|
|||||||
@@ -15,10 +15,7 @@ use cdk::cdk_lightning::{
|
|||||||
self, CreateInvoiceResponse, MintLightning, PayInvoiceResponse, PaymentQuoteResponse, Settings,
|
self, CreateInvoiceResponse, MintLightning, PayInvoiceResponse, PaymentQuoteResponse, Settings,
|
||||||
};
|
};
|
||||||
use cdk::mint::FeeReserve;
|
use cdk::mint::FeeReserve;
|
||||||
use cdk::nuts::{
|
use cdk::nuts::{CurrencyUnit, MeltQuoteBolt11Request, MeltQuoteState, MintQuoteState};
|
||||||
CurrencyUnit, MeltMethodSettings, MeltQuoteBolt11Request, MeltQuoteState, MintMethodSettings,
|
|
||||||
MintQuoteState,
|
|
||||||
};
|
|
||||||
use cdk::util::unix_time;
|
use cdk::util::unix_time;
|
||||||
use cdk::{mint, Bolt11Invoice};
|
use cdk::{mint, Bolt11Invoice};
|
||||||
use error::Error;
|
use error::Error;
|
||||||
@@ -35,8 +32,6 @@ pub mod error;
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct LNbits {
|
pub struct LNbits {
|
||||||
lnbits_api: LNBitsClient,
|
lnbits_api: LNBitsClient,
|
||||||
mint_settings: MintMethodSettings,
|
|
||||||
melt_settings: MeltMethodSettings,
|
|
||||||
fee_reserve: FeeReserve,
|
fee_reserve: FeeReserve,
|
||||||
receiver: Arc<Mutex<Option<tokio::sync::mpsc::Receiver<String>>>>,
|
receiver: Arc<Mutex<Option<tokio::sync::mpsc::Receiver<String>>>>,
|
||||||
webhook_url: String,
|
webhook_url: String,
|
||||||
@@ -51,8 +46,6 @@ impl LNbits {
|
|||||||
admin_api_key: String,
|
admin_api_key: String,
|
||||||
invoice_api_key: String,
|
invoice_api_key: String,
|
||||||
api_url: String,
|
api_url: String,
|
||||||
mint_settings: MintMethodSettings,
|
|
||||||
melt_settings: MeltMethodSettings,
|
|
||||||
fee_reserve: FeeReserve,
|
fee_reserve: FeeReserve,
|
||||||
receiver: Arc<Mutex<Option<tokio::sync::mpsc::Receiver<String>>>>,
|
receiver: Arc<Mutex<Option<tokio::sync::mpsc::Receiver<String>>>>,
|
||||||
webhook_url: String,
|
webhook_url: String,
|
||||||
@@ -61,8 +54,6 @@ impl LNbits {
|
|||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
lnbits_api,
|
lnbits_api,
|
||||||
mint_settings,
|
|
||||||
melt_settings,
|
|
||||||
receiver,
|
receiver,
|
||||||
fee_reserve,
|
fee_reserve,
|
||||||
webhook_url,
|
webhook_url,
|
||||||
@@ -80,8 +71,6 @@ impl MintLightning for LNbits {
|
|||||||
Settings {
|
Settings {
|
||||||
mpp: false,
|
mpp: false,
|
||||||
unit: CurrencyUnit::Sat,
|
unit: CurrencyUnit::Sat,
|
||||||
mint_settings: self.mint_settings.clone(),
|
|
||||||
melt_settings: self.melt_settings.clone(),
|
|
||||||
invoice_description: true,
|
invoice_description: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,10 +18,7 @@ use cdk::cdk_lightning::{
|
|||||||
self, CreateInvoiceResponse, MintLightning, PayInvoiceResponse, PaymentQuoteResponse, Settings,
|
self, CreateInvoiceResponse, MintLightning, PayInvoiceResponse, PaymentQuoteResponse, Settings,
|
||||||
};
|
};
|
||||||
use cdk::mint::FeeReserve;
|
use cdk::mint::FeeReserve;
|
||||||
use cdk::nuts::{
|
use cdk::nuts::{CurrencyUnit, MeltQuoteBolt11Request, MeltQuoteState, MintQuoteState};
|
||||||
CurrencyUnit, MeltMethodSettings, MeltQuoteBolt11Request, MeltQuoteState, MintMethodSettings,
|
|
||||||
MintQuoteState,
|
|
||||||
};
|
|
||||||
use cdk::util::{hex, unix_time};
|
use cdk::util::{hex, unix_time};
|
||||||
use cdk::{mint, Bolt11Invoice};
|
use cdk::{mint, Bolt11Invoice};
|
||||||
use error::Error;
|
use error::Error;
|
||||||
@@ -43,8 +40,6 @@ pub struct Lnd {
|
|||||||
macaroon_file: PathBuf,
|
macaroon_file: PathBuf,
|
||||||
client: Arc<Mutex<Client>>,
|
client: Arc<Mutex<Client>>,
|
||||||
fee_reserve: FeeReserve,
|
fee_reserve: FeeReserve,
|
||||||
mint_settings: MintMethodSettings,
|
|
||||||
melt_settings: MeltMethodSettings,
|
|
||||||
wait_invoice_cancel_token: CancellationToken,
|
wait_invoice_cancel_token: CancellationToken,
|
||||||
wait_invoice_is_active: Arc<AtomicBool>,
|
wait_invoice_is_active: Arc<AtomicBool>,
|
||||||
}
|
}
|
||||||
@@ -56,8 +51,6 @@ impl Lnd {
|
|||||||
cert_file: PathBuf,
|
cert_file: PathBuf,
|
||||||
macaroon_file: PathBuf,
|
macaroon_file: PathBuf,
|
||||||
fee_reserve: FeeReserve,
|
fee_reserve: FeeReserve,
|
||||||
mint_settings: MintMethodSettings,
|
|
||||||
melt_settings: MeltMethodSettings,
|
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
let client = fedimint_tonic_lnd::connect(address.to_string(), &cert_file, &macaroon_file)
|
let client = fedimint_tonic_lnd::connect(address.to_string(), &cert_file, &macaroon_file)
|
||||||
.await
|
.await
|
||||||
@@ -72,8 +65,6 @@ impl Lnd {
|
|||||||
macaroon_file,
|
macaroon_file,
|
||||||
client: Arc::new(Mutex::new(client)),
|
client: Arc::new(Mutex::new(client)),
|
||||||
fee_reserve,
|
fee_reserve,
|
||||||
mint_settings,
|
|
||||||
melt_settings,
|
|
||||||
wait_invoice_cancel_token: CancellationToken::new(),
|
wait_invoice_cancel_token: CancellationToken::new(),
|
||||||
wait_invoice_is_active: Arc::new(AtomicBool::new(false)),
|
wait_invoice_is_active: Arc::new(AtomicBool::new(false)),
|
||||||
})
|
})
|
||||||
@@ -88,8 +79,6 @@ impl MintLightning for Lnd {
|
|||||||
Settings {
|
Settings {
|
||||||
mpp: true,
|
mpp: true,
|
||||||
unit: CurrencyUnit::Msat,
|
unit: CurrencyUnit::Msat,
|
||||||
mint_settings: self.mint_settings.clone(),
|
|
||||||
melt_settings: self.melt_settings.clone(),
|
|
||||||
invoice_description: true,
|
invoice_description: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,12 +35,27 @@ pub enum LnBackend {
|
|||||||
Lnd,
|
Lnd,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct Ln {
|
pub struct Ln {
|
||||||
pub ln_backend: LnBackend,
|
pub ln_backend: LnBackend,
|
||||||
pub invoice_description: Option<String>,
|
pub invoice_description: Option<String>,
|
||||||
pub fee_percent: f32,
|
pub min_mint: Amount,
|
||||||
pub reserve_fee_min: Amount,
|
pub max_mint: Amount,
|
||||||
|
pub min_melt: Amount,
|
||||||
|
pub max_melt: Amount,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Ln {
|
||||||
|
fn default() -> Self {
|
||||||
|
Ln {
|
||||||
|
ln_backend: LnBackend::default(),
|
||||||
|
invoice_description: None,
|
||||||
|
min_mint: 1.into(),
|
||||||
|
max_mint: 500_000.into(),
|
||||||
|
min_melt: 1.into(),
|
||||||
|
max_melt: 500_000.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||||
@@ -54,11 +69,16 @@ pub struct LNbits {
|
|||||||
pub admin_api_key: String,
|
pub admin_api_key: String,
|
||||||
pub invoice_api_key: String,
|
pub invoice_api_key: String,
|
||||||
pub lnbits_api: String,
|
pub lnbits_api: String,
|
||||||
|
pub fee_percent: f32,
|
||||||
|
pub reserve_fee_min: Amount,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||||
pub struct Cln {
|
pub struct Cln {
|
||||||
pub rpc_path: PathBuf,
|
pub rpc_path: PathBuf,
|
||||||
|
pub bolt12: bool,
|
||||||
|
pub fee_percent: f32,
|
||||||
|
pub reserve_fee_min: Amount,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||||
@@ -66,23 +86,32 @@ pub struct Lnd {
|
|||||||
pub address: String,
|
pub address: String,
|
||||||
pub cert_file: PathBuf,
|
pub cert_file: PathBuf,
|
||||||
pub macaroon_file: PathBuf,
|
pub macaroon_file: PathBuf,
|
||||||
|
pub fee_percent: f32,
|
||||||
|
pub reserve_fee_min: Amount,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||||
pub struct Phoenixd {
|
pub struct Phoenixd {
|
||||||
pub api_password: String,
|
pub api_password: String,
|
||||||
pub api_url: String,
|
pub api_url: String,
|
||||||
|
pub bolt12: bool,
|
||||||
|
pub fee_percent: f32,
|
||||||
|
pub reserve_fee_min: Amount,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct FakeWallet {
|
pub struct FakeWallet {
|
||||||
pub supported_units: Vec<CurrencyUnit>,
|
pub supported_units: Vec<CurrencyUnit>,
|
||||||
|
pub fee_percent: f32,
|
||||||
|
pub reserve_fee_min: Amount,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for FakeWallet {
|
impl Default for FakeWallet {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
supported_units: vec![CurrencyUnit::Sat],
|
supported_units: vec![CurrencyUnit::Sat],
|
||||||
|
fee_percent: 0.02,
|
||||||
|
reserve_fee_min: 2.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
22
crates/cdk-mintd/src/lib.rs
Normal file
22
crates/cdk-mintd/src/lib.rs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
//! Cdk mintd lib
|
||||||
|
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
pub mod cli;
|
||||||
|
pub mod config;
|
||||||
|
pub mod setup;
|
||||||
|
|
||||||
|
fn expand_path(path: &str) -> Option<PathBuf> {
|
||||||
|
if path.starts_with('~') {
|
||||||
|
if let Some(home_dir) = home::home_dir().as_mut() {
|
||||||
|
let remainder = &path[2..];
|
||||||
|
home_dir.push(remainder);
|
||||||
|
let expanded_path = home_dir;
|
||||||
|
Some(expanded_path.clone())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Some(PathBuf::from(path))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
#![warn(missing_docs)]
|
#![warn(missing_docs)]
|
||||||
#![warn(rustdoc::bare_urls)]
|
#![warn(rustdoc::bare_urls)]
|
||||||
|
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::HashMap;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -14,33 +14,22 @@ use bip39::Mnemonic;
|
|||||||
use cdk::cdk_database::{self, MintDatabase};
|
use cdk::cdk_database::{self, MintDatabase};
|
||||||
use cdk::cdk_lightning;
|
use cdk::cdk_lightning;
|
||||||
use cdk::cdk_lightning::MintLightning;
|
use cdk::cdk_lightning::MintLightning;
|
||||||
use cdk::mint::{FeeReserve, MeltQuote, Mint};
|
use cdk::mint::{MeltQuote, Mint};
|
||||||
use cdk::mint_url::MintUrl;
|
use cdk::mint::{MintBuilder, MintMeltLimits};
|
||||||
use cdk::nuts::{
|
use cdk::nuts::{ContactInfo, CurrencyUnit, MeltQuoteState, MintVersion, PaymentMethod};
|
||||||
nut04, nut05, ContactInfo, CurrencyUnit, MeltMethodSettings, MeltQuoteState, MintInfo,
|
use cdk::types::LnKey;
|
||||||
MintMethodSettings, MintVersion, MppMethodSettings, Nuts, PaymentMethod,
|
use cdk_mintd::setup::LnBackendSetup;
|
||||||
};
|
|
||||||
use cdk::types::{LnKey, QuoteTTL};
|
|
||||||
use cdk_cln::Cln;
|
|
||||||
use cdk_fake_wallet::FakeWallet;
|
|
||||||
use cdk_lnbits::LNbits;
|
|
||||||
use cdk_lnd::Lnd;
|
|
||||||
use cdk_phoenixd::Phoenixd;
|
|
||||||
use cdk_redb::MintRedbDatabase;
|
use cdk_redb::MintRedbDatabase;
|
||||||
use cdk_sqlite::MintSqliteDatabase;
|
use cdk_sqlite::MintSqliteDatabase;
|
||||||
use cdk_strike::Strike;
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use cli::CLIArgs;
|
use tokio::sync::Notify;
|
||||||
use config::{DatabaseEngine, LnBackend};
|
|
||||||
use tokio::sync::{Mutex, Notify};
|
|
||||||
use tower_http::cors::CorsLayer;
|
use tower_http::cors::CorsLayer;
|
||||||
use tracing_subscriber::EnvFilter;
|
use tracing_subscriber::EnvFilter;
|
||||||
use url::Url;
|
|
||||||
#[cfg(feature = "swagger")]
|
#[cfg(feature = "swagger")]
|
||||||
use utoipa::OpenApi;
|
use utoipa::OpenApi;
|
||||||
|
|
||||||
mod cli;
|
use cdk_mintd::cli::CLIArgs;
|
||||||
mod config;
|
use cdk_mintd::config::{self, DatabaseEngine, LnBackend};
|
||||||
|
|
||||||
const CARGO_PKG_VERSION: Option<&'static str> = option_env!("CARGO_PKG_VERSION");
|
const CARGO_PKG_VERSION: Option<&'static str> = option_env!("CARGO_PKG_VERSION");
|
||||||
const DEFAULT_QUOTE_TTL_SECS: u64 = 1800;
|
const DEFAULT_QUOTE_TTL_SECS: u64 = 1800;
|
||||||
@@ -74,6 +63,8 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
None => work_dir.join("config.toml"),
|
None => work_dir.join("config.toml"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut mint_builder = MintBuilder::new();
|
||||||
|
|
||||||
let settings = config::Settings::new(&Some(config_file_arg));
|
let settings = config::Settings::new(&Some(config_file_arg));
|
||||||
|
|
||||||
let localstore: Arc<dyn MintDatabase<Err = cdk_database::Error> + Send + Sync> =
|
let localstore: Arc<dyn MintDatabase<Err = cdk_database::Error> + Send + Sync> =
|
||||||
@@ -92,6 +83,8 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
mint_builder = mint_builder.with_localstore(localstore);
|
||||||
|
|
||||||
let mut contact_info: Option<Vec<ContactInfo>> = None;
|
let mut contact_info: Option<Vec<ContactInfo>> = None;
|
||||||
|
|
||||||
if let Some(nostr_contact) = &settings.mint_info.contact_nostr_public_key {
|
if let Some(nostr_contact) = &settings.mint_info.contact_nostr_public_key {
|
||||||
@@ -123,324 +116,155 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
CARGO_PKG_VERSION.unwrap_or("Unknown").to_string(),
|
CARGO_PKG_VERSION.unwrap_or("Unknown").to_string(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let relative_ln_fee = settings.ln.fee_percent;
|
|
||||||
|
|
||||||
let absolute_ln_fee_reserve = settings.ln.reserve_fee_min;
|
|
||||||
|
|
||||||
let fee_reserve = FeeReserve {
|
|
||||||
min_fee_reserve: absolute_ln_fee_reserve,
|
|
||||||
percent_fee_reserve: relative_ln_fee,
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut ln_backends: HashMap<
|
let mut ln_backends: HashMap<
|
||||||
LnKey,
|
LnKey,
|
||||||
Arc<dyn MintLightning<Err = cdk_lightning::Error> + Send + Sync>,
|
Arc<dyn MintLightning<Err = cdk_lightning::Error> + Send + Sync>,
|
||||||
> = HashMap::new();
|
> = HashMap::new();
|
||||||
|
let mut ln_routers = vec![];
|
||||||
|
|
||||||
let mut supported_units = HashMap::new();
|
let mint_melt_limits = MintMeltLimits {
|
||||||
let input_fee_ppk = settings.info.input_fee_ppk.unwrap_or(0);
|
mint_min: settings.ln.min_mint,
|
||||||
|
mint_max: settings.ln.max_mint,
|
||||||
|
melt_min: settings.ln.min_melt,
|
||||||
|
melt_max: settings.ln.max_melt,
|
||||||
|
};
|
||||||
|
|
||||||
let mint_url: MintUrl = settings.info.url.parse()?;
|
match settings.ln.ln_backend {
|
||||||
|
|
||||||
let ln_routers: Vec<Router> = match settings.ln.ln_backend {
|
|
||||||
LnBackend::Cln => {
|
LnBackend::Cln => {
|
||||||
let cln_socket = expand_path(
|
let cln_settings = settings
|
||||||
settings
|
.cln
|
||||||
.cln
|
.clone()
|
||||||
.expect("Config checked at load that cln is some")
|
.expect("Config checked at load that cln is some");
|
||||||
.rpc_path
|
|
||||||
.to_str()
|
|
||||||
.ok_or(anyhow!("cln socket not defined"))?,
|
|
||||||
)
|
|
||||||
.ok_or(anyhow!("cln socket not defined"))?;
|
|
||||||
let cln = Arc::new(
|
|
||||||
Cln::new(
|
|
||||||
cln_socket,
|
|
||||||
fee_reserve,
|
|
||||||
MintMethodSettings::default(),
|
|
||||||
MeltMethodSettings::default(),
|
|
||||||
)
|
|
||||||
.await?,
|
|
||||||
);
|
|
||||||
|
|
||||||
ln_backends.insert(LnKey::new(CurrencyUnit::Sat, PaymentMethod::Bolt11), cln);
|
let cln = cln_settings
|
||||||
supported_units.insert(CurrencyUnit::Sat, (input_fee_ppk, 64));
|
.setup(&mut ln_routers, &settings, CurrencyUnit::Msat)
|
||||||
vec![]
|
.await?;
|
||||||
|
let cln = Arc::new(cln);
|
||||||
|
let ln_key = LnKey {
|
||||||
|
unit: CurrencyUnit::Sat,
|
||||||
|
method: PaymentMethod::Bolt11,
|
||||||
|
};
|
||||||
|
ln_backends.insert(ln_key, cln.clone());
|
||||||
|
|
||||||
|
mint_builder = mint_builder.add_ln_backend(
|
||||||
|
CurrencyUnit::Sat,
|
||||||
|
PaymentMethod::Bolt11,
|
||||||
|
mint_melt_limits,
|
||||||
|
cln.clone(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
LnBackend::Strike => {
|
LnBackend::Strike => {
|
||||||
let strike_settings = settings.strike.expect("Checked on config load");
|
let strike_settings = settings.clone().strike.expect("Checked on config load");
|
||||||
let api_key = strike_settings.api_key;
|
|
||||||
|
|
||||||
let units = strike_settings
|
for unit in strike_settings
|
||||||
|
.clone()
|
||||||
.supported_units
|
.supported_units
|
||||||
.unwrap_or(vec![CurrencyUnit::Sat]);
|
.unwrap_or(vec![CurrencyUnit::Sat])
|
||||||
|
{
|
||||||
let mut routers = vec![];
|
let strike = strike_settings
|
||||||
|
.setup(&mut ln_routers, &settings, unit.clone())
|
||||||
for unit in units {
|
|
||||||
// Channel used for strike web hook
|
|
||||||
let (sender, receiver) = tokio::sync::mpsc::channel(8);
|
|
||||||
let webhook_endpoint = format!("/webhook/{}/invoice", unit);
|
|
||||||
|
|
||||||
let webhook_url = mint_url.join(&webhook_endpoint)?;
|
|
||||||
|
|
||||||
let strike = Strike::new(
|
|
||||||
api_key.clone(),
|
|
||||||
MintMethodSettings::default(),
|
|
||||||
MeltMethodSettings::default(),
|
|
||||||
unit.clone(),
|
|
||||||
Arc::new(Mutex::new(Some(receiver))),
|
|
||||||
webhook_url.to_string(),
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let router = strike
|
|
||||||
.create_invoice_webhook(&webhook_endpoint, sender)
|
|
||||||
.await?;
|
.await?;
|
||||||
routers.push(router);
|
|
||||||
|
|
||||||
let ln_key = LnKey::new(unit.clone(), PaymentMethod::Bolt11);
|
mint_builder = mint_builder.add_ln_backend(
|
||||||
|
unit,
|
||||||
ln_backends.insert(ln_key, Arc::new(strike));
|
PaymentMethod::Bolt11,
|
||||||
|
mint_melt_limits,
|
||||||
supported_units.insert(unit, (input_fee_ppk, 64));
|
Arc::new(strike),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
routers
|
|
||||||
}
|
}
|
||||||
LnBackend::LNbits => {
|
LnBackend::LNbits => {
|
||||||
let lnbits_settings = settings.lnbits.expect("Checked on config load");
|
let lnbits_settings = settings.clone().lnbits.expect("Checked on config load");
|
||||||
let admin_api_key = lnbits_settings.admin_api_key;
|
let lnbits = lnbits_settings
|
||||||
let invoice_api_key = lnbits_settings.invoice_api_key;
|
.setup(&mut ln_routers, &settings, CurrencyUnit::Sat)
|
||||||
|
|
||||||
// Channel used for lnbits web hook
|
|
||||||
let (sender, receiver) = tokio::sync::mpsc::channel(8);
|
|
||||||
let webhook_endpoint = "/webhook/lnbits/sat/invoice";
|
|
||||||
|
|
||||||
let webhook_url = mint_url.join(webhook_endpoint)?;
|
|
||||||
|
|
||||||
let lnbits = LNbits::new(
|
|
||||||
admin_api_key,
|
|
||||||
invoice_api_key,
|
|
||||||
lnbits_settings.lnbits_api,
|
|
||||||
MintMethodSettings::default(),
|
|
||||||
MeltMethodSettings::default(),
|
|
||||||
fee_reserve,
|
|
||||||
Arc::new(Mutex::new(Some(receiver))),
|
|
||||||
webhook_url.to_string(),
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let router = lnbits
|
|
||||||
.create_invoice_webhook_router(webhook_endpoint, sender)
|
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let unit = CurrencyUnit::Sat;
|
mint_builder = mint_builder.add_ln_backend(
|
||||||
|
CurrencyUnit::Sat,
|
||||||
let ln_key = LnKey::new(unit.clone(), PaymentMethod::Bolt11);
|
PaymentMethod::Bolt11,
|
||||||
|
mint_melt_limits,
|
||||||
ln_backends.insert(ln_key, Arc::new(lnbits));
|
Arc::new(lnbits),
|
||||||
|
);
|
||||||
supported_units.insert(unit, (input_fee_ppk, 64));
|
|
||||||
vec![router]
|
|
||||||
}
|
}
|
||||||
LnBackend::Phoenixd => {
|
LnBackend::Phoenixd => {
|
||||||
let api_password = settings
|
let phd_settings = settings.clone().phoenixd.expect("Checked at config load");
|
||||||
.clone()
|
let phd = phd_settings
|
||||||
.phoenixd
|
.setup(&mut ln_routers, &settings, CurrencyUnit::Sat)
|
||||||
.expect("Checked at config load")
|
|
||||||
.api_password;
|
|
||||||
|
|
||||||
let api_url = settings
|
|
||||||
.clone()
|
|
||||||
.phoenixd
|
|
||||||
.expect("Checked at config load")
|
|
||||||
.api_url;
|
|
||||||
|
|
||||||
if fee_reserve.percent_fee_reserve < 0.04 {
|
|
||||||
bail!("Fee reserve is too low needs to be at least 0.02");
|
|
||||||
}
|
|
||||||
|
|
||||||
let webhook_endpoint = "/webhook/phoenixd";
|
|
||||||
|
|
||||||
let mint_url = Url::parse(&settings.info.url)?;
|
|
||||||
|
|
||||||
let webhook_url = mint_url.join(webhook_endpoint)?.to_string();
|
|
||||||
|
|
||||||
let (sender, receiver) = tokio::sync::mpsc::channel(8);
|
|
||||||
|
|
||||||
let phoenixd = Phoenixd::new(
|
|
||||||
api_password.to_string(),
|
|
||||||
api_url.to_string(),
|
|
||||||
MintMethodSettings::default(),
|
|
||||||
MeltMethodSettings::default(),
|
|
||||||
fee_reserve,
|
|
||||||
Arc::new(Mutex::new(Some(receiver))),
|
|
||||||
webhook_url,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let router = phoenixd
|
|
||||||
.create_invoice_webhook(webhook_endpoint, sender)
|
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
supported_units.insert(CurrencyUnit::Sat, (input_fee_ppk, 64));
|
mint_builder = mint_builder.add_ln_backend(
|
||||||
ln_backends.insert(
|
CurrencyUnit::Sat,
|
||||||
LnKey {
|
PaymentMethod::Bolt11,
|
||||||
unit: CurrencyUnit::Sat,
|
mint_melt_limits,
|
||||||
method: PaymentMethod::Bolt11,
|
Arc::new(phd),
|
||||||
},
|
|
||||||
Arc::new(phoenixd),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
vec![router]
|
|
||||||
}
|
}
|
||||||
LnBackend::Lnd => {
|
LnBackend::Lnd => {
|
||||||
let lnd_settings = settings.lnd.expect("Checked at config load");
|
let lnd_settings = settings.clone().lnd.expect("Checked at config load");
|
||||||
|
let lnd = lnd_settings
|
||||||
|
.setup(&mut ln_routers, &settings, CurrencyUnit::Msat)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let address = lnd_settings.address;
|
mint_builder = mint_builder.add_ln_backend(
|
||||||
let cert_file = lnd_settings.cert_file;
|
CurrencyUnit::Sat,
|
||||||
let macaroon_file = lnd_settings.macaroon_file;
|
PaymentMethod::Bolt11,
|
||||||
|
mint_melt_limits,
|
||||||
let lnd = Lnd::new(
|
|
||||||
address,
|
|
||||||
cert_file,
|
|
||||||
macaroon_file,
|
|
||||||
fee_reserve,
|
|
||||||
MintMethodSettings::default(),
|
|
||||||
MeltMethodSettings::default(),
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
supported_units.insert(CurrencyUnit::Sat, (input_fee_ppk, 64));
|
|
||||||
ln_backends.insert(
|
|
||||||
LnKey {
|
|
||||||
unit: CurrencyUnit::Sat,
|
|
||||||
method: PaymentMethod::Bolt11,
|
|
||||||
},
|
|
||||||
Arc::new(lnd),
|
Arc::new(lnd),
|
||||||
);
|
);
|
||||||
|
|
||||||
vec![]
|
|
||||||
}
|
}
|
||||||
LnBackend::FakeWallet => {
|
LnBackend::FakeWallet => {
|
||||||
let units = settings.fake_wallet.unwrap_or_default().supported_units;
|
let fake_wallet = settings.clone().fake_wallet.expect("Fake wallet defined");
|
||||||
|
|
||||||
for unit in units {
|
for unit in fake_wallet.clone().supported_units {
|
||||||
let ln_key = LnKey::new(unit.clone(), PaymentMethod::Bolt11);
|
let fake = fake_wallet
|
||||||
|
.setup(&mut ln_routers, &settings, CurrencyUnit::Sat)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let wallet = Arc::new(FakeWallet::new(
|
let fake = Arc::new(fake);
|
||||||
fee_reserve.clone(),
|
|
||||||
MintMethodSettings::default(),
|
|
||||||
MeltMethodSettings::default(),
|
|
||||||
HashMap::default(),
|
|
||||||
HashSet::default(),
|
|
||||||
0,
|
|
||||||
));
|
|
||||||
|
|
||||||
ln_backends.insert(ln_key, wallet);
|
mint_builder = mint_builder.add_ln_backend(
|
||||||
|
unit.clone(),
|
||||||
supported_units.insert(unit, (input_fee_ppk, 64));
|
PaymentMethod::Bolt11,
|
||||||
|
mint_melt_limits,
|
||||||
|
fake.clone(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
vec![]
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let (nut04_settings, nut05_settings, mpp_settings): (
|
|
||||||
nut04::Settings,
|
|
||||||
nut05::Settings,
|
|
||||||
Vec<MppMethodSettings>,
|
|
||||||
) = ln_backends.iter().fold(
|
|
||||||
(
|
|
||||||
nut04::Settings::new(vec![], false),
|
|
||||||
nut05::Settings::new(vec![], false),
|
|
||||||
Vec::new(),
|
|
||||||
),
|
|
||||||
|(mut nut_04, mut nut_05, mut mpp), (key, ln)| {
|
|
||||||
let settings = ln.get_settings();
|
|
||||||
|
|
||||||
let m = MppMethodSettings {
|
|
||||||
method: key.method,
|
|
||||||
unit: key.unit.clone(),
|
|
||||||
mpp: settings.mpp,
|
|
||||||
};
|
|
||||||
|
|
||||||
let n4 = MintMethodSettings {
|
|
||||||
method: key.method,
|
|
||||||
unit: key.unit.clone(),
|
|
||||||
min_amount: settings.mint_settings.min_amount,
|
|
||||||
max_amount: settings.mint_settings.max_amount,
|
|
||||||
description: settings.invoice_description,
|
|
||||||
};
|
|
||||||
|
|
||||||
let n5 = MeltMethodSettings {
|
|
||||||
method: key.method,
|
|
||||||
unit: key.unit.clone(),
|
|
||||||
min_amount: settings.melt_settings.min_amount,
|
|
||||||
max_amount: settings.melt_settings.max_amount,
|
|
||||||
};
|
|
||||||
|
|
||||||
nut_04.methods.push(n4);
|
|
||||||
nut_05.methods.push(n5);
|
|
||||||
mpp.push(m);
|
|
||||||
|
|
||||||
(nut_04, nut_05, mpp)
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
let nuts = Nuts::new()
|
|
||||||
.nut04(nut04_settings)
|
|
||||||
.nut05(nut05_settings)
|
|
||||||
.nut07(true)
|
|
||||||
.nut08(true)
|
|
||||||
.nut09(true)
|
|
||||||
.nut10(true)
|
|
||||||
.nut11(true)
|
|
||||||
.nut12(true)
|
|
||||||
.nut14(true)
|
|
||||||
.nut15(mpp_settings);
|
|
||||||
|
|
||||||
let mut mint_info = MintInfo::new()
|
|
||||||
.name(settings.mint_info.name)
|
|
||||||
.version(mint_version)
|
|
||||||
.description(settings.mint_info.description)
|
|
||||||
.nuts(nuts);
|
|
||||||
|
|
||||||
if let Some(long_description) = &settings.mint_info.description_long {
|
if let Some(long_description) = &settings.mint_info.description_long {
|
||||||
mint_info = mint_info.long_description(long_description);
|
mint_builder = mint_builder.with_long_description(long_description.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(contact_info) = contact_info {
|
if let Some(contact_info) = contact_info {
|
||||||
mint_info = mint_info.contact_info(contact_info);
|
for info in contact_info {
|
||||||
|
mint_builder = mint_builder.add_contact_info(info);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(pubkey) = settings.mint_info.pubkey {
|
if let Some(pubkey) = settings.mint_info.pubkey {
|
||||||
mint_info = mint_info.pubkey(pubkey);
|
mint_builder = mint_builder.with_pubkey(pubkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(icon_url) = &settings.mint_info.icon_url {
|
if let Some(icon_url) = &settings.mint_info.icon_url {
|
||||||
mint_info = mint_info.icon_url(icon_url);
|
mint_builder = mint_builder.with_icon_url(icon_url.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(motd) = settings.mint_info.motd {
|
if let Some(motd) = settings.mint_info.motd {
|
||||||
mint_info = mint_info.motd(motd);
|
mint_builder = mint_builder.with_motd(motd);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mnemonic = Mnemonic::from_str(&settings.info.mnemonic)?;
|
let mnemonic = Mnemonic::from_str(&settings.info.mnemonic)?;
|
||||||
|
|
||||||
let quote_ttl = QuoteTTL::new(10000, 10000);
|
mint_builder = mint_builder
|
||||||
|
.with_name(settings.mint_info.name)
|
||||||
|
.with_mint_url(settings.info.url)
|
||||||
|
.with_version(mint_version)
|
||||||
|
.with_description(settings.mint_info.description)
|
||||||
|
.with_quote_ttl(10000, 10000)
|
||||||
|
.with_seed(mnemonic.to_seed_normalized("").to_vec());
|
||||||
|
|
||||||
let mint = Mint::new(
|
let mint = mint_builder.build().await?;
|
||||||
&settings.info.url,
|
|
||||||
&mnemonic.to_seed_normalized(""),
|
|
||||||
mint_info,
|
|
||||||
quote_ttl,
|
|
||||||
localstore,
|
|
||||||
ln_backends.clone(),
|
|
||||||
supported_units,
|
|
||||||
HashMap::new(),
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let mint = Arc::new(mint);
|
let mint = Arc::new(mint);
|
||||||
|
|
||||||
@@ -530,14 +354,14 @@ async fn check_pending_mint_quotes(
|
|||||||
ln: Arc<dyn MintLightning<Err = cdk_lightning::Error> + Send + Sync>,
|
ln: Arc<dyn MintLightning<Err = cdk_lightning::Error> + Send + Sync>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let mut pending_quotes = mint.get_pending_mint_quotes().await?;
|
let mut pending_quotes = mint.get_pending_mint_quotes().await?;
|
||||||
tracing::trace!("There are {} pending mint quotes.", pending_quotes.len());
|
tracing::info!("There are {} pending mint quotes.", pending_quotes.len());
|
||||||
let mut unpaid_quotes = mint.get_unpaid_mint_quotes().await?;
|
let mut unpaid_quotes = mint.get_unpaid_mint_quotes().await?;
|
||||||
tracing::trace!("There are {} unpaid mint quotes.", unpaid_quotes.len());
|
tracing::info!("There are {} unpaid mint quotes.", unpaid_quotes.len());
|
||||||
|
|
||||||
unpaid_quotes.append(&mut pending_quotes);
|
unpaid_quotes.append(&mut pending_quotes);
|
||||||
|
|
||||||
for quote in unpaid_quotes {
|
for quote in unpaid_quotes {
|
||||||
tracing::trace!("Checking status of mint quote: {}", quote.id);
|
tracing::debug!("Checking status of mint quote: {}", quote.id);
|
||||||
let lookup_id = quote.request_lookup_id;
|
let lookup_id = quote.request_lookup_id;
|
||||||
match ln.check_incoming_invoice_status(&lookup_id).await {
|
match ln.check_incoming_invoice_status(&lookup_id).await {
|
||||||
Ok(state) => {
|
Ok(state) => {
|
||||||
@@ -568,8 +392,10 @@ async fn check_pending_melt_quotes(
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|q| q.state == MeltQuoteState::Pending || q.state == MeltQuoteState::Unknown)
|
.filter(|q| q.state == MeltQuoteState::Pending || q.state == MeltQuoteState::Unknown)
|
||||||
.collect();
|
.collect();
|
||||||
|
tracing::info!("There are {} pending melt quotes.", pending_quotes.len());
|
||||||
|
|
||||||
for pending_quote in pending_quotes {
|
for pending_quote in pending_quotes {
|
||||||
|
tracing::debug!("Checking status for melt quote {}.", pending_quote.id);
|
||||||
let melt_request_ln_key = mint.localstore.get_melt_request(&pending_quote.id).await?;
|
let melt_request_ln_key = mint.localstore.get_melt_request(&pending_quote.id).await?;
|
||||||
|
|
||||||
let (melt_request, ln_key) = match melt_request_ln_key {
|
let (melt_request, ln_key) = match melt_request_ln_key {
|
||||||
@@ -646,21 +472,6 @@ async fn check_pending_melt_quotes(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expand_path(path: &str) -> Option<PathBuf> {
|
|
||||||
if path.starts_with('~') {
|
|
||||||
if let Some(home_dir) = home::home_dir().as_mut() {
|
|
||||||
let remainder = &path[2..];
|
|
||||||
home_dir.push(remainder);
|
|
||||||
let expanded_path = home_dir;
|
|
||||||
Some(expanded_path.clone())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Some(PathBuf::from(path))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn work_dir() -> Result<PathBuf> {
|
fn work_dir() -> Result<PathBuf> {
|
||||||
let home_dir = home::home_dir().ok_or(anyhow!("Unknown home dir"))?;
|
let home_dir = home::home_dir().ok_or(anyhow!("Unknown home dir"))?;
|
||||||
|
|
||||||
|
|||||||
229
crates/cdk-mintd/src/setup.rs
Normal file
229
crates/cdk-mintd/src/setup.rs
Normal file
@@ -0,0 +1,229 @@
|
|||||||
|
use std::{
|
||||||
|
collections::{HashMap, HashSet},
|
||||||
|
sync::Arc,
|
||||||
|
};
|
||||||
|
|
||||||
|
use anyhow::{anyhow, bail};
|
||||||
|
use axum::{async_trait, Router};
|
||||||
|
|
||||||
|
use cdk::{cdk_lightning::MintLightning, mint::FeeReserve, mint_url::MintUrl, nuts::CurrencyUnit};
|
||||||
|
use tokio::sync::Mutex;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
config::{self, Settings},
|
||||||
|
expand_path,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
pub trait LnBackendSetup {
|
||||||
|
async fn setup(
|
||||||
|
&self,
|
||||||
|
routers: &mut Vec<Router>,
|
||||||
|
settings: &Settings,
|
||||||
|
unit: CurrencyUnit,
|
||||||
|
) -> anyhow::Result<impl MintLightning>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl LnBackendSetup for config::Cln {
|
||||||
|
async fn setup(
|
||||||
|
&self,
|
||||||
|
_routers: &mut Vec<Router>,
|
||||||
|
_settings: &Settings,
|
||||||
|
_unit: CurrencyUnit,
|
||||||
|
) -> anyhow::Result<cdk_cln::Cln> {
|
||||||
|
let cln_socket = expand_path(
|
||||||
|
self.rpc_path
|
||||||
|
.to_str()
|
||||||
|
.ok_or(anyhow!("cln socket not defined"))?,
|
||||||
|
)
|
||||||
|
.ok_or(anyhow!("cln socket not defined"))?;
|
||||||
|
|
||||||
|
let fee_reserve = FeeReserve {
|
||||||
|
min_fee_reserve: self.reserve_fee_min,
|
||||||
|
percent_fee_reserve: self.fee_percent,
|
||||||
|
};
|
||||||
|
|
||||||
|
let cln = cdk_cln::Cln::new(cln_socket, fee_reserve).await?;
|
||||||
|
|
||||||
|
Ok(cln)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl LnBackendSetup for config::Strike {
|
||||||
|
async fn setup(
|
||||||
|
&self,
|
||||||
|
routers: &mut Vec<Router>,
|
||||||
|
settings: &Settings,
|
||||||
|
unit: CurrencyUnit,
|
||||||
|
) -> anyhow::Result<cdk_strike::Strike> {
|
||||||
|
let api_key = &self.api_key;
|
||||||
|
|
||||||
|
// Channel used for strike web hook
|
||||||
|
let (sender, receiver) = tokio::sync::mpsc::channel(8);
|
||||||
|
let webhook_endpoint = format!("/webhook/{}/invoice", unit);
|
||||||
|
|
||||||
|
let mint_url: MintUrl = settings.info.url.parse()?;
|
||||||
|
let webhook_url = mint_url.join(&webhook_endpoint)?;
|
||||||
|
|
||||||
|
let strike = cdk_strike::Strike::new(
|
||||||
|
api_key.clone(),
|
||||||
|
unit,
|
||||||
|
Arc::new(Mutex::new(Some(receiver))),
|
||||||
|
webhook_url.to_string(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let router = strike
|
||||||
|
.create_invoice_webhook(&webhook_endpoint, sender)
|
||||||
|
.await?;
|
||||||
|
routers.push(router);
|
||||||
|
|
||||||
|
Ok(strike)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl LnBackendSetup for config::LNbits {
|
||||||
|
async fn setup(
|
||||||
|
&self,
|
||||||
|
routers: &mut Vec<Router>,
|
||||||
|
settings: &Settings,
|
||||||
|
_unit: CurrencyUnit,
|
||||||
|
) -> anyhow::Result<cdk_lnbits::LNbits> {
|
||||||
|
let admin_api_key = &self.admin_api_key;
|
||||||
|
let invoice_api_key = &self.invoice_api_key;
|
||||||
|
|
||||||
|
// Channel used for lnbits web hook
|
||||||
|
let (sender, receiver) = tokio::sync::mpsc::channel(8);
|
||||||
|
let webhook_endpoint = "/webhook/lnbits/sat/invoice";
|
||||||
|
|
||||||
|
let mint_url: MintUrl = settings.info.url.parse()?;
|
||||||
|
let webhook_url = mint_url.join(webhook_endpoint)?;
|
||||||
|
|
||||||
|
let fee_reserve = FeeReserve {
|
||||||
|
min_fee_reserve: self.reserve_fee_min,
|
||||||
|
percent_fee_reserve: self.fee_percent,
|
||||||
|
};
|
||||||
|
|
||||||
|
let lnbits = cdk_lnbits::LNbits::new(
|
||||||
|
admin_api_key.clone(),
|
||||||
|
invoice_api_key.clone(),
|
||||||
|
self.lnbits_api.clone(),
|
||||||
|
fee_reserve,
|
||||||
|
Arc::new(Mutex::new(Some(receiver))),
|
||||||
|
webhook_url.to_string(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let router = lnbits
|
||||||
|
.create_invoice_webhook_router(webhook_endpoint, sender)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
routers.push(router);
|
||||||
|
|
||||||
|
Ok(lnbits)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl LnBackendSetup for config::Phoenixd {
|
||||||
|
async fn setup(
|
||||||
|
&self,
|
||||||
|
routers: &mut Vec<Router>,
|
||||||
|
settings: &Settings,
|
||||||
|
_unit: CurrencyUnit,
|
||||||
|
) -> anyhow::Result<cdk_phoenixd::Phoenixd> {
|
||||||
|
let api_password = &self.api_password;
|
||||||
|
|
||||||
|
let api_url = &self.api_url;
|
||||||
|
|
||||||
|
let fee_reserve = FeeReserve {
|
||||||
|
min_fee_reserve: self.reserve_fee_min,
|
||||||
|
percent_fee_reserve: self.fee_percent,
|
||||||
|
};
|
||||||
|
|
||||||
|
if fee_reserve.percent_fee_reserve < 0.04 {
|
||||||
|
bail!("Fee reserve is too low needs to be at least 0.02");
|
||||||
|
}
|
||||||
|
|
||||||
|
let webhook_endpoint = "/webhook/phoenixd";
|
||||||
|
|
||||||
|
let mint_url = Url::parse(&settings.info.url)?;
|
||||||
|
|
||||||
|
let webhook_url = mint_url.join(webhook_endpoint)?.to_string();
|
||||||
|
|
||||||
|
let (sender, receiver) = tokio::sync::mpsc::channel(8);
|
||||||
|
|
||||||
|
let phoenixd = cdk_phoenixd::Phoenixd::new(
|
||||||
|
api_password.to_string(),
|
||||||
|
api_url.to_string(),
|
||||||
|
fee_reserve,
|
||||||
|
Arc::new(Mutex::new(Some(receiver))),
|
||||||
|
webhook_url,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let router = phoenixd
|
||||||
|
.create_invoice_webhook(webhook_endpoint, sender)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
routers.push(router);
|
||||||
|
|
||||||
|
Ok(phoenixd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl LnBackendSetup for config::Lnd {
|
||||||
|
async fn setup(
|
||||||
|
&self,
|
||||||
|
_routers: &mut Vec<Router>,
|
||||||
|
_settings: &Settings,
|
||||||
|
_unit: CurrencyUnit,
|
||||||
|
) -> anyhow::Result<cdk_lnd::Lnd> {
|
||||||
|
let address = &self.address;
|
||||||
|
let cert_file = &self.cert_file;
|
||||||
|
let macaroon_file = &self.macaroon_file;
|
||||||
|
|
||||||
|
let fee_reserve = FeeReserve {
|
||||||
|
min_fee_reserve: self.reserve_fee_min,
|
||||||
|
percent_fee_reserve: self.fee_percent,
|
||||||
|
};
|
||||||
|
|
||||||
|
let lnd = cdk_lnd::Lnd::new(
|
||||||
|
address.to_string(),
|
||||||
|
cert_file.clone(),
|
||||||
|
macaroon_file.clone(),
|
||||||
|
fee_reserve,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(lnd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl LnBackendSetup for config::FakeWallet {
|
||||||
|
async fn setup(
|
||||||
|
&self,
|
||||||
|
_router: &mut Vec<Router>,
|
||||||
|
_settings: &Settings,
|
||||||
|
_unit: CurrencyUnit,
|
||||||
|
) -> anyhow::Result<cdk_fake_wallet::FakeWallet> {
|
||||||
|
let fee_reserve = FeeReserve {
|
||||||
|
min_fee_reserve: self.reserve_fee_min,
|
||||||
|
percent_fee_reserve: self.fee_percent,
|
||||||
|
};
|
||||||
|
|
||||||
|
let fake_wallet = cdk_fake_wallet::FakeWallet::new(
|
||||||
|
fee_reserve,
|
||||||
|
HashMap::default(),
|
||||||
|
HashSet::default(),
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(fake_wallet)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,10 +15,7 @@ use cdk::cdk_lightning::{
|
|||||||
self, CreateInvoiceResponse, MintLightning, PayInvoiceResponse, PaymentQuoteResponse, Settings,
|
self, CreateInvoiceResponse, MintLightning, PayInvoiceResponse, PaymentQuoteResponse, Settings,
|
||||||
};
|
};
|
||||||
use cdk::mint::FeeReserve;
|
use cdk::mint::FeeReserve;
|
||||||
use cdk::nuts::{
|
use cdk::nuts::{CurrencyUnit, MeltQuoteBolt11Request, MeltQuoteState, MintQuoteState};
|
||||||
CurrencyUnit, MeltMethodSettings, MeltQuoteBolt11Request, MeltQuoteState, MintMethodSettings,
|
|
||||||
MintQuoteState,
|
|
||||||
};
|
|
||||||
use cdk::{mint, Bolt11Invoice};
|
use cdk::{mint, Bolt11Invoice};
|
||||||
use error::Error;
|
use error::Error;
|
||||||
use futures::{Stream, StreamExt};
|
use futures::{Stream, StreamExt};
|
||||||
@@ -32,8 +29,6 @@ pub mod error;
|
|||||||
/// Phoenixd
|
/// Phoenixd
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Phoenixd {
|
pub struct Phoenixd {
|
||||||
mint_settings: MintMethodSettings,
|
|
||||||
melt_settings: MeltMethodSettings,
|
|
||||||
phoenixd_api: PhoenixdApi,
|
phoenixd_api: PhoenixdApi,
|
||||||
fee_reserve: FeeReserve,
|
fee_reserve: FeeReserve,
|
||||||
receiver: Arc<Mutex<Option<tokio::sync::mpsc::Receiver<WebhookResponse>>>>,
|
receiver: Arc<Mutex<Option<tokio::sync::mpsc::Receiver<WebhookResponse>>>>,
|
||||||
@@ -47,16 +42,12 @@ impl Phoenixd {
|
|||||||
pub fn new(
|
pub fn new(
|
||||||
api_password: String,
|
api_password: String,
|
||||||
api_url: String,
|
api_url: String,
|
||||||
mint_settings: MintMethodSettings,
|
|
||||||
melt_settings: MeltMethodSettings,
|
|
||||||
fee_reserve: FeeReserve,
|
fee_reserve: FeeReserve,
|
||||||
receiver: Arc<Mutex<Option<tokio::sync::mpsc::Receiver<WebhookResponse>>>>,
|
receiver: Arc<Mutex<Option<tokio::sync::mpsc::Receiver<WebhookResponse>>>>,
|
||||||
webhook_url: String,
|
webhook_url: String,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
let phoenixd = PhoenixdApi::new(&api_password, &api_url)?;
|
let phoenixd = PhoenixdApi::new(&api_password, &api_url)?;
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
mint_settings,
|
|
||||||
melt_settings,
|
|
||||||
phoenixd_api: phoenixd,
|
phoenixd_api: phoenixd,
|
||||||
fee_reserve,
|
fee_reserve,
|
||||||
receiver,
|
receiver,
|
||||||
@@ -86,8 +77,6 @@ impl MintLightning for Phoenixd {
|
|||||||
Settings {
|
Settings {
|
||||||
mpp: false,
|
mpp: false,
|
||||||
unit: CurrencyUnit::Sat,
|
unit: CurrencyUnit::Sat,
|
||||||
mint_settings: self.mint_settings.clone(),
|
|
||||||
melt_settings: self.melt_settings.clone(),
|
|
||||||
invoice_description: true,
|
invoice_description: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,10 +14,7 @@ use cdk::amount::Amount;
|
|||||||
use cdk::cdk_lightning::{
|
use cdk::cdk_lightning::{
|
||||||
self, CreateInvoiceResponse, MintLightning, PayInvoiceResponse, PaymentQuoteResponse, Settings,
|
self, CreateInvoiceResponse, MintLightning, PayInvoiceResponse, PaymentQuoteResponse, Settings,
|
||||||
};
|
};
|
||||||
use cdk::nuts::{
|
use cdk::nuts::{CurrencyUnit, MeltQuoteBolt11Request, MeltQuoteState, MintQuoteState};
|
||||||
CurrencyUnit, MeltMethodSettings, MeltQuoteBolt11Request, MeltQuoteState, MintMethodSettings,
|
|
||||||
MintQuoteState,
|
|
||||||
};
|
|
||||||
use cdk::util::unix_time;
|
use cdk::util::unix_time;
|
||||||
use cdk::{mint, Bolt11Invoice};
|
use cdk::{mint, Bolt11Invoice};
|
||||||
use error::Error;
|
use error::Error;
|
||||||
@@ -37,8 +34,6 @@ pub mod error;
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Strike {
|
pub struct Strike {
|
||||||
strike_api: StrikeApi,
|
strike_api: StrikeApi,
|
||||||
mint_settings: MintMethodSettings,
|
|
||||||
melt_settings: MeltMethodSettings,
|
|
||||||
unit: CurrencyUnit,
|
unit: CurrencyUnit,
|
||||||
receiver: Arc<Mutex<Option<tokio::sync::mpsc::Receiver<String>>>>,
|
receiver: Arc<Mutex<Option<tokio::sync::mpsc::Receiver<String>>>>,
|
||||||
webhook_url: String,
|
webhook_url: String,
|
||||||
@@ -50,8 +45,6 @@ impl Strike {
|
|||||||
/// Create new [`Strike`] wallet
|
/// Create new [`Strike`] wallet
|
||||||
pub async fn new(
|
pub async fn new(
|
||||||
api_key: String,
|
api_key: String,
|
||||||
mint_settings: MintMethodSettings,
|
|
||||||
melt_settings: MeltMethodSettings,
|
|
||||||
unit: CurrencyUnit,
|
unit: CurrencyUnit,
|
||||||
receiver: Arc<Mutex<Option<tokio::sync::mpsc::Receiver<String>>>>,
|
receiver: Arc<Mutex<Option<tokio::sync::mpsc::Receiver<String>>>>,
|
||||||
webhook_url: String,
|
webhook_url: String,
|
||||||
@@ -59,8 +52,6 @@ impl Strike {
|
|||||||
let strike = StrikeApi::new(&api_key, None)?;
|
let strike = StrikeApi::new(&api_key, None)?;
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
strike_api: strike,
|
strike_api: strike,
|
||||||
mint_settings,
|
|
||||||
melt_settings,
|
|
||||||
receiver,
|
receiver,
|
||||||
unit,
|
unit,
|
||||||
webhook_url,
|
webhook_url,
|
||||||
@@ -78,8 +69,6 @@ impl MintLightning for Strike {
|
|||||||
Settings {
|
Settings {
|
||||||
mpp: false,
|
mpp: false,
|
||||||
unit: self.unit.clone(),
|
unit: self.unit.clone(),
|
||||||
mint_settings: self.mint_settings.clone(),
|
|
||||||
melt_settings: self.melt_settings.clone(),
|
|
||||||
invoice_description: true,
|
invoice_description: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,10 +8,7 @@ use lightning_invoice::{Bolt11Invoice, ParseOrSemanticError};
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::nuts::{
|
use crate::nuts::{CurrencyUnit, MeltQuoteBolt11Request, MeltQuoteState, MintQuoteState};
|
||||||
CurrencyUnit, MeltMethodSettings, MeltQuoteBolt11Request, MeltQuoteState, MintMethodSettings,
|
|
||||||
MintQuoteState,
|
|
||||||
};
|
|
||||||
use crate::{mint, Amount};
|
use crate::{mint, Amount};
|
||||||
|
|
||||||
/// CDK Lightning Error
|
/// CDK Lightning Error
|
||||||
@@ -148,10 +145,6 @@ pub struct PaymentQuoteResponse {
|
|||||||
pub struct Settings {
|
pub struct Settings {
|
||||||
/// MPP supported
|
/// MPP supported
|
||||||
pub mpp: bool,
|
pub mpp: bool,
|
||||||
/// Min amount to mint
|
|
||||||
pub mint_settings: MintMethodSettings,
|
|
||||||
/// Max amount to mint
|
|
||||||
pub melt_settings: MeltMethodSettings,
|
|
||||||
/// Base unit of backend
|
/// Base unit of backend
|
||||||
pub unit: CurrencyUnit,
|
pub unit: CurrencyUnit,
|
||||||
/// Invoice Description supported
|
/// Invoice Description supported
|
||||||
|
|||||||
Reference in New Issue
Block a user