Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ jobs:
-p cdk-cln,
-p cdk-lnd,
-p cdk-strike,
-p cdk-nwc,
-p cdk-lnbits,
-p cdk-fake-wallet,
-p cdk-payment-processor,
Expand Down Expand Up @@ -344,6 +345,7 @@ jobs:
-p cdk-cln,
-p cdk-lnd,
-p cdk-strike,
-p cdk-nwc,
-p cdk-mint-rpc,
-p cdk-sqlite,
-p cdk-mintd,
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ cdk-lnbits = { path = "./crates/cdk-lnbits", version = "=0.13.0" }
cdk-lnd = { path = "./crates/cdk-lnd", version = "=0.13.0" }
cdk-ldk-node = { path = "./crates/cdk-ldk-node", version = "=0.13.0" }
cdk-strike = { path = "./crates/cdk-strike", version = "=0.13.0" }
cdk-nwc = { path = "./crates/cdk-nwc", version = "=0.13.0" }
cdk-fake-wallet = { path = "./crates/cdk-fake-wallet", version = "=0.13.0" }
cdk-ffi = { path = "./crates/cdk-ffi", version = "=0.13.0" }
cdk-payment-processor = { path = "./crates/cdk-payment-processor", default-features = true, version = "=0.13.0" }
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ The project is split up into several crates in the `crates/` directory:
* [**cdk-lnbits**](./crates/cdk-lnbits/): [LNbits](https://lnbits.com/) Lightning backend for mint. **Note: Only LNBits v1 API is supported.**
* [**cdk-ldk-node**](./crates/cdk-ldk-node/): LDK Node Lightning backend for mint.
* [**cdk-strike**](./crates/cdk-strike/): Strike Lightning backend for mint with BTC and USD support.
* [**cdk-strike**](./crates/cdk-nwc): Nostr Wallet Connect (NWC) Lightning backend for mint.
* [**cdk-fake-wallet**](./crates/cdk-fake-wallet/): Fake Lightning backend for mint. To be used only for testing, quotes are automatically filled.
* [**cdk-mint-rpc**](./crates/cdk-mint-rpc/): Mint management gRPC server and cli.
* Binaries:
Expand Down
3 changes: 2 additions & 1 deletion crates/cdk-integration-tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ cdk-axum = { workspace = true, features = ["auth"] }
cdk-sqlite = { workspace = true }
cdk-redb = { workspace = true }
cdk-fake-wallet = { workspace = true }
cdk-nwc = { workspace = true }
cdk-common = { workspace = true, features = ["mint", "wallet", "auth"] }
cdk-mintd = { workspace = true, features = ["cln", "lnd", "fakewallet", "grpc-processor", "auth", "lnbits", "management-rpc", "sqlite", "postgres", "ldk-node", "prometheus", "strike"] }
cdk-mintd = { workspace = true, features = ["cln", "lnd", "fakewallet", "grpc-processor", "auth", "lnbits", "management-rpc", "sqlite", "postgres", "ldk-node", "prometheus", "strike", "nwc"] }
futures = { workspace = true, default-features = false, features = [
"executor",
] }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@ fn create_ldk_settings(
lnd: None,
ldk_node: Some(ldk_config),
fake_wallet: None,
nwc: None,
grpc_processor: None,
database: cdk_mintd::config::Database::default(),
auth_database: None,
Expand Down
3 changes: 3 additions & 0 deletions crates/cdk-integration-tests/src/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ pub fn create_fake_wallet_settings(
lnd: None,
ldk_node: None,
fake_wallet: fake_wallet_config,
nwc: None,
grpc_processor: None,
database: Database {
engine: DatabaseEngine::from_str(database).expect("valid database"),
Expand Down Expand Up @@ -270,6 +271,7 @@ pub fn create_cln_settings(
lnd: None,
ldk_node: None,
fake_wallet: None,
nwc: None,
grpc_processor: None,
database: cdk_mintd::config::Database::default(),
auth_database: None,
Expand Down Expand Up @@ -320,6 +322,7 @@ pub fn create_lnd_settings(
ldk_node: None,
lnd: Some(lnd_config),
fake_wallet: None,
nwc: None,
grpc_processor: None,
database: cdk_mintd::config::Database::default(),
auth_database: None,
Expand Down
4 changes: 3 additions & 1 deletion crates/cdk-mintd/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ rust-version.workspace = true
readme = "README.md"

[features]
default = ["management-rpc", "cln", "lnd", "lnbits", "fakewallet", "grpc-processor", "sqlite", "strike"]
default = ["management-rpc", "cln", "lnd", "lnbits", "fakewallet", "grpc-processor", "sqlite", "strike", "nwc"]
# Database features - at least one must be enabled
sqlite = ["dep:cdk-sqlite"]
postgres = ["dep:cdk-postgres"]
Expand All @@ -24,6 +24,7 @@ fakewallet = ["dep:cdk-fake-wallet"]
ldk-node = ["dep:cdk-ldk-node"]
grpc-processor = ["dep:cdk-payment-processor", "cdk-signatory/grpc"]
sqlcipher = ["sqlite", "cdk-sqlite/sqlcipher"]
nwc = ["dep:cdk-nwc"]
# MSRV is not committed to with swagger enabled
swagger = ["cdk-axum/swagger", "dep:utoipa", "dep:utoipa-swagger-ui"]
auth = ["cdk/auth", "cdk-axum/auth", "cdk-sqlite?/auth", "cdk-postgres?/auth"]
Expand All @@ -48,6 +49,7 @@ cdk-lnd = { workspace = true, optional = true }
cdk-ldk-node = { workspace = true, optional = true }
cdk-fake-wallet = { workspace = true, optional = true }
cdk-strike = { workspace = true, optional = true }
cdk-nwc = { workspace = true, optional = true }
cdk-axum.workspace = true
cdk-signatory.workspace = true
cdk-mint-rpc = { workspace = true, optional = true }
Expand Down
7 changes: 6 additions & 1 deletion crates/cdk-mintd/example.config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ max_connections = 20
connection_timeout_seconds = 10

[ln]
# Required ln backend `cln`, `lnd`, `fakewallet`, 'lnbits', 'ldknode', 'strike'
# Required ln backend `cln`, `lnd`, `fakewallet`, 'lnbits', 'ldknode', 'strike', 'nwc'
ln_backend = "fakewallet"
# min_mint=1
# max_mint=500000
Expand Down Expand Up @@ -159,6 +159,11 @@ reserve_fee_min = 1
min_delay_time = 1
max_delay_time = 3

# [nwc]
# nwc_uri = "nostr+walletconnect://..."
# fee_percent = 0.02
# reserve_fee_min = 1

# [grpc_processor]
# gRPC Payment Processor configuration
# supported_units = ["sat"]
Expand Down
21 changes: 21 additions & 0 deletions crates/cdk-mintd/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ pub enum LnBackend {
GrpcProcessor,
#[cfg(feature = "strike")]
Strike,
#[cfg(feature = "nwc")]
Nwc,
}

impl std::str::FromStr for LnBackend {
Expand All @@ -161,6 +163,8 @@ impl std::str::FromStr for LnBackend {
"grpcprocessor" => Ok(LnBackend::GrpcProcessor),
#[cfg(feature = "strike")]
"strike" => Ok(LnBackend::Strike),
#[cfg(feature = "nwc")]
"nwc" => Ok(LnBackend::Nwc),
_ => Err(format!("Unknown Lightning backend: {s}")),
}
}
Expand Down Expand Up @@ -305,6 +309,14 @@ fn default_webserver_port() -> Option<u16> {
Some(8091)
}

#[cfg(feature = "nwc")]
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct Nwc {
pub nwc_uri: String,
pub fee_percent: f32,
pub reserve_fee_min: Amount,
}

#[cfg(feature = "fakewallet")]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FakeWallet {
Expand Down Expand Up @@ -492,6 +504,8 @@ pub struct Settings {
pub lnd: Option<Lnd>,
#[cfg(feature = "ldk-node")]
pub ldk_node: Option<LdkNode>,
#[cfg(feature = "nwc")]
pub nwc: Option<Nwc>,
#[cfg(feature = "fakewallet")]
pub fake_wallet: Option<FakeWallet>,
pub grpc_processor: Option<GrpcProcessor>,
Expand Down Expand Up @@ -638,6 +652,13 @@ impl Settings {
"Strike backend requires a valid config."
)
}
#[cfg(feature = "nwc")]
LnBackend::Nwc => {
assert!(
settings.nwc.is_some(),
"NWC backend requires a valid config."
)
}
}

Ok(settings)
Expand Down
8 changes: 8 additions & 0 deletions crates/cdk-mintd/src/env_vars/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ mod lnbits;
mod lnd;
#[cfg(feature = "management-rpc")]
mod management_rpc;
#[cfg(feature = "nwc")]
mod nwc;
#[cfg(feature = "prometheus")]
mod prometheus;
#[cfg(feature = "strike")]
Expand Down Expand Up @@ -54,6 +56,8 @@ pub use lnd::*;
#[cfg(feature = "management-rpc")]
pub use management_rpc::*;
pub use mint_info::*;
#[cfg(feature = "nwc")]
pub use nwc::*;
#[cfg(feature = "prometheus")]
pub use prometheus::*;
#[cfg(feature = "strike")]
Expand Down Expand Up @@ -156,6 +160,10 @@ impl Settings {
LnBackend::Strike => {
self.strike = Some(self.strike.clone().unwrap_or_default().from_env());
}
#[cfg(feature = "nwc")]
LnBackend::Nwc => {
self.nwc = Some(self.nwc.clone().unwrap_or_default().from_env());
}
LnBackend::None => bail!("Ln backend must be set"),
#[allow(unreachable_patterns)]
_ => bail!("Selected Ln backend is not enabled in this build"),
Expand Down
32 changes: 32 additions & 0 deletions crates/cdk-mintd/src/env_vars/nwc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//! NWC environment variables

use std::env;

use crate::config::Nwc;

// NWC environment variables
pub const ENV_NWC_URI: &str = "CDK_MINTD_NWC_URI";
pub const ENV_NWC_FEE_PERCENT: &str = "CDK_MINTD_NWC_FEE_PERCENT";
pub const ENV_NWC_RESERVE_FEE_MIN: &str = "CDK_MINTD_NWC_RESERVE_FEE_MIN";

impl Nwc {
pub fn from_env(mut self) -> Self {
if let Ok(nwc_uri) = env::var(ENV_NWC_URI) {
self.nwc_uri = nwc_uri;
}

if let Ok(fee_str) = env::var(ENV_NWC_FEE_PERCENT) {
if let Ok(fee) = fee_str.parse() {
self.fee_percent = fee;
}
}

if let Ok(reserve_fee_str) = env::var(ENV_NWC_RESERVE_FEE_MIN) {
if let Ok(reserve_fee) = reserve_fee_str.parse::<u64>() {
self.reserve_fee_min = reserve_fee.into();
}
}

self
}
}
25 changes: 22 additions & 3 deletions crates/cdk-mintd/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ use cdk::mint::{Mint, MintBuilder, MintMeltLimits};
feature = "lnd",
feature = "ldk-node",
feature = "fakewallet",
feature = "grpc-processor"
feature = "grpc-processor",
feature = "nwc"
))]
use cdk::nuts::nut17::SupportedMethods;
use cdk::nuts::nut19::{CachedEndpoint, Method as NUT19Method, Path as NUT19Path};
Expand All @@ -30,7 +31,8 @@ use cdk::nuts::nut19::{CachedEndpoint, Method as NUT19Method, Path as NUT19Path}
feature = "lnbits",
feature = "lnd",
feature = "ldk-node",
feature = "fakewallet"
feature = "fakewallet",
feature = "nwc"
))]
use cdk::nuts::CurrencyUnit;
#[cfg(feature = "auth")]
Expand Down Expand Up @@ -581,6 +583,22 @@ async fn configure_lightning_backend(

return Ok((mint_builder, webhook_routers));
}
#[cfg(feature = "nwc")]
LnBackend::Nwc => {
let nwc_settings = settings.clone().nwc.expect("NWC config defined");
let nwc = nwc_settings
.setup(settings, CurrencyUnit::Sat, None, work_dir, None)
.await?;

mint_builder = configure_backend_for_unit(
settings,
mint_builder,
CurrencyUnit::Sat,
mint_melt_limits,
Arc::new(nwc),
)
.await?;
}
LnBackend::None => {
tracing::error!(
"Payment backend was not set or feature disabled. {:?}",
Expand Down Expand Up @@ -639,7 +657,8 @@ async fn configure_backend_for_unit(
feature = "fakewallet",
feature = "grpc-processor",
feature = "ldk-node",
feature = "strike"
feature = "strike",
feature = "nwc"
))]
{
let nut17_supported = SupportedMethods::default_bolt11(unit);
Expand Down
28 changes: 27 additions & 1 deletion crates/cdk-mintd/src/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ use cdk::nuts::CurrencyUnit;
feature = "cln",
feature = "lnd",
feature = "ldk-node",
feature = "fakewallet"
feature = "fakewallet",
feature = "nwc"
))]
use cdk::types::FeeReserve;

Expand Down Expand Up @@ -369,3 +370,28 @@ impl config::Strike {
Ok((strike, webhook_router))
}
}

#[cfg(feature = "nwc")]
#[async_trait]
impl LnBackendSetup for config::Nwc {
async fn setup(
&self,
settings: &Settings,
unit: CurrencyUnit,
_runtime: Option<std::sync::Arc<tokio::runtime::Runtime>>,
_work_dir: &Path,
_kv_store: Option<Arc<dyn MintKVStore<Err = cdk::cdk_database::Error> + Send + Sync>>,
) -> anyhow::Result<cdk_nwc::NWCWallet> {
let fee_reserve = FeeReserve {
min_fee_reserve: self.reserve_fee_min,
percent_fee_reserve: self.fee_percent,
};

let internal_settlement_only = settings.ln.internal_settlement_only;

let nwc =
cdk_nwc::NWCWallet::new(&self.nwc_uri, fee_reserve, unit, internal_settlement_only)
.await?;
Ok(nwc)
}
}
25 changes: 25 additions & 0 deletions crates/cdk-nwc/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
[package]
name = "cdk-nwc"
version.workspace = true
edition.workspace = true
authors = ["CDK Developers"]
license.workspace = true
homepage = "https://github.com/cashubtc/cdk"
repository = "https://github.com/cashubtc/cdk.git"
rust-version.workspace = true # MSRV
description = "CDK nwc backend"
readme = "README.md"

[dependencies]
nwc = "0.43.0"
async-trait.workspace = true
bitcoin.workspace = true
cdk-common = { workspace = true, features = ["mint"] }
futures.workspace = true
tokio.workspace = true
tokio-util.workspace = true
tracing.workspace = true
thiserror.workspace = true
serde_json.workspace = true
tokio-stream = { workspace = true, features = ["sync"] }
rustls.workspace = true
Loading
Loading