diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c55fe200..c7dde5c9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -102,7 +102,6 @@ jobs: -p cdk-cln, -p cdk-lnd, -p cdk-phoenixd, - -p cdk-strike, -p cdk-lnbits, -p cdk-fake-wallet, --bin cdk-cli, @@ -111,6 +110,7 @@ jobs: --bin cdk-mintd --no-default-features --features redis, --bin cdk-mintd --no-default-features --features "redis swagger", --bin cdk-mintd --no-default-features --features management-rpc, + --bin cdk-mintd --no-default-features --features redb, --bin cdk-mint-cli, ] steps: @@ -216,12 +216,14 @@ jobs: -p cdk --no-default-features --features "mint mint", -p cdk-axum, -p cdk-axum --no-default-features --features redis, - -p cdk-strike, -p cdk-lnbits, -p cdk-phoenixd, -p cdk-fake-wallet, -p cdk-cln, + -p cdk-lnd, -p cdk-mint-rpc, + -p cdk-sqlite, + -p cdk-mintd, ] steps: - name: checkout @@ -236,29 +238,6 @@ jobs: run: nix develop -i -L .#msrv --command cargo build ${{ matrix.build-args }} - db-msrv-build: - name: "DB MSRV build" - runs-on: ubuntu-latest - timeout-minutes: 15 - strategy: - matrix: - build-args: - [ - -p cdk-sqlite, - -p cdk-redb, - ] - steps: - - name: checkout - uses: actions/checkout@v4 - - name: Install Nix - uses: DeterminateSystems/nix-installer-action@v11 - - name: Nix Cache - uses: DeterminateSystems/magic-nix-cache-action@v6 - - name: Rust Cache - uses: Swatinem/rust-cache@v2 - - name: Build - run: nix develop -i -L .#db_shell --command cargo build ${{ matrix.build-args }} - check-wasm: name: Check WASM runs-on: ubuntu-latest diff --git a/Cargo.toml b/Cargo.toml index a04e2503..bf935411 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,13 +5,69 @@ members = [ resolver = "2" [workspace.package] +edition = "2021" +rust-version = "1.75.0" license = "MIT" homepage = "https://github.com/cashubtc/cdk" repository = "https://github.com/cashubtc/cdk.git" +[workspace.dependencies] +anyhow = "1" +async-trait = "0.1" +axum = { version = "0.8.1", features = ["ws"] } +bitcoin = { version = "0.32.2", features = ["base64", "serde", "rand", "rand-std"] } +bip39 = { version = "2.0", features = ["rand"] } +cashu = { path = "./crates/cashu", version = "=0.7.1" } +cdk = { path = "./crates/cdk", default-features = false, version = "=0.7.2" } +cdk-common = { path = "./crates/cdk-common", default-features = false, version = "=0.7.1" } +cdk-axum = { path = "./crates/cdk-axum", default-features = false, version = "=0.7.1" } +cdk-cln = { path = "./crates/cdk-cln", version = "=0.7.1" } +cdk-lnbits = { path = "./crates/cdk-lnbits", version = "=0.7.1" } +cdk-lnd = { path = "./crates/cdk-lnd", version = "=0.7.1" } +cdk-phoenixd = { path = "./crates/cdk-phoenixd", version = "=0.7.1" } +cdk-fake-wallet = { path = "./crates/cdk-fake-wallet", version = "=0.7.1" } +cdk-mint-rpc = { path = "./crates/cdk-mint-rpc", version = "=0.7.1" } +cdk-redb = { path = "./crates/cdk-redb", default-features = true, version = "=0.7.1" } +cdk-sqlite = { path = "./crates/cdk-sqlite", default-features = true, version = "=0.7.1" } +clap = { version = "4.5.31", features = ["derive"] } +ciborium = { version = "0.2.2", default-features = false, features = ["std"] } +cbor-diag = "0.1.12" +futures = { version = "0.3.28", default-features = false, features = ["async-await"] } +lightning-invoice = { version = "0.32.0", features = ["serde", "std"] } +serde = { version = "1", features = ["derive"] } +serde_json = "1" +thiserror = { version = "1" } +tokio = { version = "1", default-features = false } +tokio-util = { version = "0.7.11", default-features = false } +tower-http = { version = "0.6.1", features = ["compression-full", "decompression-full", "cors", "trace"] } +tokio-tungstenite = { version = "0.26.0", default-features = false } +tracing = { version = "0.1", default-features = false, features = ["attributes", "log"] } +tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } +url = "2.3" +uuid = { version = "=1.12.1", features = ["v4", "serde"] } +utoipa = { version = "5.3.1", features = [ + "preserve_order", + "preserve_path_order", +]} +serde_with = "3" +reqwest = { version = "0.12", default-features = false, features = [ + "json", + "rustls-tls", + "rustls-tls-native-roots", + "socks", + "zstd", + "brotli", + "gzip", + "deflate", +]} +once_cell = "1.20.2" +instant = { version = "0.1", default-features = false } +rand = "0.8.5" +home = "0.5.5" + + [workspace.metadata] authors = ["CDK Developers"] -edition = "2021" description = "Cashu Development Kit" readme = "README.md" repository = "https://github.com/cashubtc/cdk" diff --git a/README.md b/README.md index a68d7dad..c3a119d5 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,6 @@ The project is split up into several crates in the `crates/` directory: * [**cdk-axum**](./crates/cdk-axum/): Axum webserver for mint. * [**cdk-cln**](./crates/cdk-cln/): CLN Lightning backend for mint. * [**cdk-lnd**](./crates/cdk-lnd/): Lnd Lightning backend for mint. - * [**cdk-strike**](./crates/cdk-strike/): Strike Lightning backend for mint. * [**cdk-lnbits**](./crates/cdk-lnbits/): [LNbits](https://lnbits.com/) Lightning backend for mint. * [**cdk-phoenixd**](./crates/cdk-phoenixd/): Phoenixd 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. diff --git a/crates/cashu/Cargo.toml b/crates/cashu/Cargo.toml index be491cb9..1930192b 100644 --- a/crates/cashu/Cargo.toml +++ b/crates/cashu/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "cashu" version = "0.7.1" -edition = "2021" +edition.workspace = true authors = ["CDK Developers"] description = "Cashu shared types and crypto utilities, used as the foundation for the CDK and their crates" homepage = "https://github.com/cashubtc/cdk" repository = "https://github.com/cashubtc/cdk.git" -rust-version = "1.63.0" # MSRV -license = "MIT" +rust-version = "1.75.0" # MSRV +license.workspace = true [features] default = ["mint", "wallet"] @@ -17,28 +17,23 @@ wallet = [] bench = [] [dependencies] -uuid = { version = "=1.12.1", features = ["v4", "serde"], optional = true } -bitcoin = { version = "0.32.2", features = [ - "base64", - "serde", - "rand", - "rand-std", -] } -cbor-diag = "0.1.12" -ciborium = { version = "0.2.2", default-features = false, features = ["std"] } -once_cell = "1.20.2" -serde = { version = "1", features = ["derive"] } -lightning-invoice = { version = "0.32.0", features = ["serde", "std"] } -thiserror = "2" -tracing = "0.1" -url = "2.3" -utoipa = { version = "4", optional = true } -serde_json = "1" -serde_with = "3" +uuid = { workspace = true, optional = true } +bitcoin.workspace = true +cbor-diag.workspace = true +ciborium.workspace = true +once_cell.workspace = true +serde.workspace = true +lightning-invoice.workspace = true +thiserror.workspace = true +tracing.workspace = true +url.workspace = true +utoipa = { workspace = true, optional = true } +serde_json.workspace = true +serde_with.workspace = true [target.'cfg(target_arch = "wasm32")'.dependencies] -instant = { version = "0.1", features = ["wasm-bindgen", "inaccurate"] } +instant = { workspace = true, features = ["wasm-bindgen", "inaccurate"] } [dev-dependencies] -bip39 = "2.0" -uuid = { version = "=1.12.1", features = ["v4", "serde"] } +bip39.workspace = true +uuid.workspace = true diff --git a/crates/cashu/src/nuts/nut03.rs b/crates/cashu/src/nuts/nut03.rs index 0f12ad79..0627631e 100644 --- a/crates/cashu/src/nuts/nut03.rs +++ b/crates/cashu/src/nuts/nut03.rs @@ -40,7 +40,7 @@ pub struct PreSwap { #[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))] pub struct SwapRequest { /// Proofs that are to be spent in a `Swap` - #[cfg_attr(feature = "swagger", schema(value_type = Vec))] + #[cfg_attr(feature = "swagger", schema(value_type = Vec))] pub inputs: Proofs, /// Blinded Messages for Mint to sign pub outputs: Vec, diff --git a/crates/cashu/src/nuts/nut05.rs b/crates/cashu/src/nuts/nut05.rs index 4981dea4..b1a3bbcf 100644 --- a/crates/cashu/src/nuts/nut05.rs +++ b/crates/cashu/src/nuts/nut05.rs @@ -335,7 +335,7 @@ pub struct MeltBolt11Request { /// Quote ID pub quote: Q, /// Proofs - #[cfg_attr(feature = "swagger", schema(value_type = Vec))] + #[cfg_attr(feature = "swagger", schema(value_type = Vec))] pub inputs: Proofs, /// Blinded Message that can be used to return change [NUT-08] /// Amount field of BlindedMessages `SHOULD` be set to zero diff --git a/crates/cashu/src/nuts/nut17/mod.rs b/crates/cashu/src/nuts/nut17/mod.rs index 11e68624..33e11e21 100644 --- a/crates/cashu/src/nuts/nut17/mod.rs +++ b/crates/cashu/src/nuts/nut17/mod.rs @@ -27,6 +27,7 @@ pub struct Params { /// Check state Settings #[derive(Debug, Default, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))] pub struct SupportedSettings { /// Supported methods pub supported: Vec, @@ -34,6 +35,7 @@ pub struct SupportedSettings { /// Supported WS Methods #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))] pub struct SupportedMethods { /// Payment Method pub method: PaymentMethod, diff --git a/crates/cashu/src/nuts/nut19.rs b/crates/cashu/src/nuts/nut19.rs index 6d97b6be..6434fdf9 100644 --- a/crates/cashu/src/nuts/nut19.rs +++ b/crates/cashu/src/nuts/nut19.rs @@ -16,6 +16,7 @@ pub struct Settings { /// List of the methods and paths for which caching is enabled #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))] pub struct CachedEndpoint { /// HTTP Method pub method: Method, @@ -33,6 +34,7 @@ impl CachedEndpoint { /// HTTP method #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "UPPERCASE")] +#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))] pub enum Method { /// Get Get, @@ -42,6 +44,7 @@ pub enum Method { /// Route path #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[cfg_attr(feature = "swagger", derive(utoipa::ToSchema))] pub enum Path { /// Bolt11 Mint #[serde(rename = "/v1/mint/bolt11")] diff --git a/crates/cdk-axum/Cargo.toml b/crates/cdk-axum/Cargo.toml index 0240bafe..d2d8482d 100644 --- a/crates/cdk-axum/Cargo.toml +++ b/crates/cdk-axum/Cargo.toml @@ -1,40 +1,35 @@ [package] name = "cdk-axum" version = "0.7.1" -edition = "2021" -license = "MIT" +edition.workspace = true +license.workspace = true homepage = "https://github.com/cashubtc/cdk" repository = "https://github.com/cashubtc/cdk.git" -rust-version = "1.63.0" # MSRV +rust-version = "1.75.0" # MSRV description = "Cashu CDK axum webserver" +[features] +redis = ["dep:redis"] +swagger = ["cdk/swagger", "dep:utoipa"] + [dependencies] -anyhow = "1" -async-trait = "0.1.83" -axum = { version = "0.6.20", features = ["ws"] } -cdk = { path = "../cdk", version = "0.7.1", default-features = false, features = [ +anyhow.workspace = true +async-trait.workspace = true +axum = { workspace = true, features = ["ws"] } +cdk = { workspace = true, features = [ "mint", ] } -tokio = { version = "1", default-features = false, features = ["io-util"] } -tracing = { version = "0.1", default-features = false, features = [ - "attributes", - "log", -] } -utoipa = { version = "4", features = [ - "preserve_order", - "preserve_path_order", -], optional = true } -futures = { version = "0.3.28", default-features = false } +tokio.workspace = true +tracing.workspace = true +utoipa = { workspace = true, optional = true } +futures.workspace = true moka = { version = "0.11.1", features = ["future"] } -serde_json = "1" +serde_json.workspace = true paste = "1.0.15" -serde = { version = "1", features = ["derive"] } -uuid = { version = "1", features = ["v4", "serde"] } +serde.workspace = true +uuid.workspace = true sha2 = "0.10.8" redis = { version = "0.23.3", features = [ "tokio-rustls-comp", ], optional = true } -[features] -redis = ["dep:redis"] -swagger = ["cdk/swagger", "dep:utoipa"] diff --git a/crates/cdk-axum/src/cache/mod.rs b/crates/cdk-axum/src/cache/mod.rs index d4ed27d2..b755da82 100644 --- a/crates/cdk-axum/src/cache/mod.rs +++ b/crates/cdk-axum/src/cache/mod.rs @@ -117,7 +117,7 @@ impl HttpCache { tti: Duration, storage: Option>, ) -> Self { - let mut storage = storage.unwrap_or_else(|| Box::new(InMemoryHttpCache::default())); + let mut storage = storage.unwrap_or_else(|| Box::::default()); storage.set_expiration_times(ttl, tti); Self { diff --git a/crates/cdk-axum/src/lib.rs b/crates/cdk-axum/src/lib.rs index 9a60bf0e..6e696b56 100644 --- a/crates/cdk-axum/src/lib.rs +++ b/crates/cdk-axum/src/lib.rs @@ -45,8 +45,6 @@ mod swagger_imports { #[cfg(feature = "swagger")] use swagger_imports::*; -#[cfg(feature = "swagger")] -use uuid::Uuid; /// CDK Mint State #[derive(Clone)] @@ -75,16 +73,16 @@ pub struct MintState { KeysetResponse, KeySet, KeySetInfo, - MeltBolt11Request, + MeltBolt11Request, MeltQuoteBolt11Request, - MeltQuoteBolt11Response, + MeltQuoteBolt11Response, MeltQuoteState, MeltMethodSettings, - MintBolt11Request, + MintBolt11Request, MintBolt11Response, MintInfo, MintQuoteBolt11Request, - MintQuoteBolt11Response, + MintQuoteBolt11Response, MintQuoteState, MintMethodSettings, MintVersion, @@ -148,18 +146,18 @@ pub async fn create_mint_router_with_custom_cache( let v1_router = Router::new() .route("/keys", get(get_keys)) .route("/keysets", get(get_keysets)) - .route("/keys/:keyset_id", get(get_keyset_pubkeys)) + .route("/keys/{keyset_id}", get(get_keyset_pubkeys)) .route("/swap", post(cache_post_swap)) .route("/mint/quote/bolt11", post(post_mint_bolt11_quote)) .route( - "/mint/quote/bolt11/:quote_id", + "/mint/quote/bolt11/{quote_id}", get(get_check_mint_bolt11_quote), ) .route("/mint/bolt11", post(cache_post_mint_bolt11)) .route("/melt/quote/bolt11", post(post_melt_bolt11_quote)) .route("/ws", get(ws_handler)) .route( - "/melt/quote/bolt11/:quote_id", + "/melt/quote/bolt11/{quote_id}", get(get_check_melt_bolt11_quote), ) .route("/melt/bolt11", post(cache_post_melt_bolt11)) diff --git a/crates/cdk-axum/src/router_handlers.rs b/crates/cdk-axum/src/router_handlers.rs index e91719fb..1960073a 100644 --- a/crates/cdk-axum/src/router_handlers.rs +++ b/crates/cdk-axum/src/router_handlers.rs @@ -137,7 +137,7 @@ pub async fn get_keysets(State(state): State) -> Result, content_type = "application/json"), (status = 500, description = "Server error", body = ErrorResponse, content_type = "application/json") ) ))] @@ -165,7 +165,7 @@ pub async fn post_mint_bolt11_quote( ("quote_id" = String, description = "The quote ID"), ), responses( - (status = 200, description = "Successful response", body = MintQuoteBolt11Response, content_type = "application/json"), + (status = 200, description = "Successful response", body = MintQuoteBolt11Response, content_type = "application/json"), (status = 500, description = "Server error", body = ErrorResponse, content_type = "application/json") ) ))] @@ -201,7 +201,7 @@ pub async fn ws_handler(State(state): State, ws: WebSocketUpgrade) -> post, context_path = "/v1", path = "/mint/bolt11", - request_body(content = MintBolt11Request, description = "Request params", content_type = "application/json"), + request_body(content = MintBolt11Request, description = "Request params", content_type = "application/json"), responses( (status = 200, description = "Successful response", body = MintBolt11Response, content_type = "application/json"), (status = 500, description = "Server error", body = ErrorResponse, content_type = "application/json") @@ -229,7 +229,7 @@ pub async fn post_mint_bolt11( path = "/melt/quote/bolt11", request_body(content = MeltQuoteBolt11Request, description = "Quote params", content_type = "application/json"), responses( - (status = 200, description = "Successful response", body = MeltQuoteBolt11Response, content_type = "application/json"), + (status = 200, description = "Successful response", body = MeltQuoteBolt11Response, content_type = "application/json"), (status = 500, description = "Server error", body = ErrorResponse, content_type = "application/json") ) ))] @@ -256,7 +256,7 @@ pub async fn post_melt_bolt11_quote( ("quote_id" = String, description = "The quote ID"), ), responses( - (status = 200, description = "Successful response", body = MeltQuoteBolt11Response, content_type = "application/json"), + (status = 200, description = "Successful response", body = MeltQuoteBolt11Response, content_type = "application/json"), (status = 500, description = "Server error", body = ErrorResponse, content_type = "application/json") ) ))] @@ -284,9 +284,9 @@ pub async fn get_check_melt_bolt11_quote( post, context_path = "/v1", path = "/melt/bolt11", - request_body(content = MeltBolt11Request, description = "Melt params", content_type = "application/json"), + request_body(content = MeltBolt11Request, description = "Melt params", content_type = "application/json"), responses( - (status = 200, description = "Successful response", body = MeltQuoteBolt11Response, content_type = "application/json"), + (status = 200, description = "Successful response", body = MeltQuoteBolt11Response, content_type = "application/json"), (status = 500, description = "Server error", body = ErrorResponse, content_type = "application/json") ) ))] diff --git a/crates/cdk-axum/src/ws/mod.rs b/crates/cdk-axum/src/ws/mod.rs index 6357134f..03f41af1 100644 --- a/crates/cdk-axum/src/ws/mod.rs +++ b/crates/cdk-axum/src/ws/mod.rs @@ -46,7 +46,6 @@ pub struct WsContext { /// /// For simplicity sake this function will spawn tasks for each subscription and /// keep them in a hashmap, and will have a single subscriber for all of them. -#[allow(clippy::incompatible_msrv)] pub async fn main_websocket(mut socket: WebSocket, state: MintState) { let (publisher, mut subscriber) = mpsc::channel(100); let mut context = WsContext { @@ -75,7 +74,7 @@ pub async fn main_websocket(mut socket: WebSocket, state: MintState) { } }; - if let Err(err)= socket.send(Message::Text(message)).await { + if let Err(err)= socket.send(Message::Text(message.into())).await { tracing::error!("Could not send websocket message: {}", err); break; } @@ -92,7 +91,7 @@ pub async fn main_websocket(mut socket: WebSocket, state: MintState) { match process(&mut context, request).await { Ok(result) => { if let Err(err) = socket - .send(Message::Text(result.to_string())) + .send(Message::Text(result.to_string().into())) .await { tracing::error!("Could not send request: {}", err); diff --git a/crates/cdk-cli/Cargo.toml b/crates/cdk-cli/Cargo.toml index d61d3fc3..4e258d45 100644 --- a/crates/cdk-cli/Cargo.toml +++ b/crates/cdk-cli/Cargo.toml @@ -1,42 +1,33 @@ [package] name = "cdk-cli" version = "0.7.1" -edition = "2021" authors = ["CDK Developers"] description = "Cashu cli wallet built on CDK" -license = "MIT" -homepage = "https://github.com/cashubtc/cdk" -repository = "https://github.com/cashubtc/cdk.git" -rust-version = "1.63.0" # MSRV - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +license.workspace = true +homepage.workspace = true +repository.workspace = true +edition.workspace = true +rust-version.workspace = true [dependencies] -anyhow = "1" -bip39 = { version = "2.0", features = ["rand"] } -cdk = { path = "../cdk", version = "0.7.1", default-features = false, features = ["wallet"]} -cdk-redb = { path = "../cdk-redb", version = "0.7.1", default-features = false, features = ["wallet"] } -cdk-sqlite = { path = "../cdk-sqlite", version = "0.7.1", default-features = false, features = ["wallet"] } -clap = { version = "~4.0.32", features = ["derive"] } -serde = { version = "1", default-features = false, features = ["derive"] } -serde_json = "1" -tokio = { version = "1", default-features = false } -tracing = { version = "0.1", default-features = false, features = ["attributes", "log"] } -tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } -home = "0.5.5" +anyhow.workspace = true +bip39.workspace = true +cdk = { workspace = true, default-features = false, features = ["wallet"]} +cdk-redb = { workspace = true, features = ["wallet"] } +cdk-sqlite = { workspace = true, features = ["wallet"] } +clap.workspace = true +serde.workspace = true +serde_json.workspace = true +tokio.workspace = true +tracing.workspace = true +tracing-subscriber.workspace = true +home.workspace = true nostr-sdk = { version = "0.35.0", default-features = false, features = [ "nip04", "nip44", "nip59" ]} -reqwest = { version = "0.12", default-features = false, features = [ - "json", - "rustls-tls", - "rustls-tls-native-roots", - "socks", -]} -url = "2.3" - -# Indirect dep -base64ct = "=1.6.0" +reqwest.workspace = true +url.workspace = true +serde_with.workspace = true diff --git a/crates/cdk-cln/Cargo.toml b/crates/cdk-cln/Cargo.toml index 99574973..64064c00 100644 --- a/crates/cdk-cln/Cargo.toml +++ b/crates/cdk-cln/Cargo.toml @@ -6,17 +6,17 @@ authors = ["CDK Developers"] license = "MIT" homepage = "https://github.com/cashubtc/cdk" repository = "https://github.com/cashubtc/cdk.git" -rust-version = "1.63.0" # MSRV +rust-version = "1.75.0" # MSRV description = "CDK ln backend for cln" [dependencies] -async-trait = "0.1" -bitcoin = { version = "0.32.2", default-features = false } -cdk = { path = "../cdk", version = "0.7.1", default-features = false, features = ["mint"] } +async-trait.workspace = true +bitcoin.workspace = true +cdk = { workspace = true, features = ["mint"] } cln-rpc = "0.3.0" -futures = { version = "0.3.28", default-features = false } -tokio = { version = "1", default-features = false } -tokio-util = { version = "0.7.11", default-features = false } -tracing = { version = "0.1", default-features = false, features = ["attributes", "log"] } -thiserror = "1" -uuid = { version = "1", features = ["v4"] } +futures.workspace = true +tokio.workspace = true +tokio-util.workspace = true +tracing.workspace = true +thiserror.workspace = true +uuid.workspace = true diff --git a/crates/cdk-cln/src/lib.rs b/crates/cdk-cln/src/lib.rs index 4dacff4f..bb4ab218 100644 --- a/crates/cdk-cln/src/lib.rs +++ b/crates/cdk-cln/src/lib.rs @@ -81,8 +81,6 @@ impl MintLightning for Cln { self.wait_invoice_cancel_token.cancel() } - #[allow(clippy::incompatible_msrv)] - // Clippy thinks select is not stable but it compiles fine on MSRV (1.63.0) async fn wait_any_invoice( &self, ) -> Result + Send>>, Self::Err> { diff --git a/crates/cdk-common/Cargo.toml b/crates/cdk-common/Cargo.toml index 8d797214..4aca1428 100644 --- a/crates/cdk-common/Cargo.toml +++ b/crates/cdk-common/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "cdk-common" version = "0.7.1" -edition = "2021" authors = ["CDK Developers"] description = "CDK common types and traits" homepage = "https://github.com/cashubtc/cdk" repository = "https://github.com/cashubtc/cdk.git" -rust-version = "1.63.0" # MSRV -license = "MIT" +edition.workspace = true +rust-version = "1.75.0" # MSRV +license.workspace = true [features] default = ["mint", "wallet"] @@ -17,31 +17,26 @@ wallet = ["cashu/wallet"] mint = ["cashu/mint", "dep:uuid"] [dependencies] -async-trait = "0.1" -bitcoin = { version = "0.32.2", features = [ - "base64", - "serde", - "rand", - "rand-std", -] } -cashu = { path = "../cashu", default-features = false, version = "0.7.1" } -cbor-diag = "0.1.12" -ciborium = { version = "0.2.2", default-features = false, features = ["std"] } -serde = { version = "1", features = ["derive"] } -lightning-invoice = { version = "0.32.0", features = ["serde", "std"] } -thiserror = "2" -tracing = "0.1" -url = "2.3" -uuid = { version = "=1.12.1", features = ["v4", "serde"], optional = true } -utoipa = { version = "4", optional = true } -futures = "0.3.31" -anyhow = "1.0" -serde_json = "1" -serde_with = "3" +async-trait.workspace = true +bitcoin.workspace = true +cashu.workspace = true +cbor-diag.workspace = true +ciborium.workspace = true +serde.workspace = true +lightning-invoice.workspace = true +thiserror.workspace = true +tracing.workspace = true +url.workspace = true +uuid = { workspace = true, optional = true } +utoipa = { workspace = true, optional = true } +futures.workspace = true +anyhow.workspace = true +serde_json.workspace = true +serde_with.workspace = true [target.'cfg(target_arch = "wasm32")'.dependencies] -instant = { version = "0.1", features = ["wasm-bindgen", "inaccurate"] } +instant = { workspace = true, features = ["wasm-bindgen", "inaccurate"] } [dev-dependencies] -rand = "0.8.5" -bip39 = "2.0" +rand.workspace = true +bip39.workspace = true diff --git a/crates/cdk-common/src/lib.rs b/crates/cdk-common/src/lib.rs index 52e7068e..d83cc5a5 100644 --- a/crates/cdk-common/src/lib.rs +++ b/crates/cdk-common/src/lib.rs @@ -12,7 +12,6 @@ pub mod error; #[cfg(feature = "mint")] pub mod lightning; pub mod pub_sub; -#[cfg(feature = "mint")] pub mod subscription; pub mod ws; diff --git a/crates/cdk-common/src/subscription.rs b/crates/cdk-common/src/subscription.rs index 3d62270c..ba14de1b 100644 --- a/crates/cdk-common/src/subscription.rs +++ b/crates/cdk-common/src/subscription.rs @@ -1,11 +1,18 @@ //! Subscription types and traits +#[cfg(feature = "mint")] use std::str::FromStr; -use cashu::nut17::{self, Error, Kind, Notification}; +use cashu::nut17::{self}; +#[cfg(feature = "mint")] +use cashu::nut17::{Error, Kind, Notification}; +#[cfg(feature = "mint")] use cashu::{NotificationPayload, PublicKey}; +#[cfg(feature = "mint")] use serde::{Deserialize, Serialize}; +#[cfg(feature = "mint")] use uuid::Uuid; +#[cfg(feature = "mint")] use crate::pub_sub::index::{Index, Indexable, SubscriptionGlobalId}; use crate::pub_sub::SubId; @@ -15,15 +22,18 @@ use crate::pub_sub::SubId; pub type Params = nut17::Params; /// Wrapper around `nut17::Params` to implement `Indexable` for `Notification`. +#[cfg(feature = "mint")] #[derive(Debug, Clone, Serialize, Deserialize)] pub struct IndexableParams(Params); +#[cfg(feature = "mint")] impl From for IndexableParams { fn from(params: Params) -> Self { Self(params) } } +#[cfg(feature = "mint")] impl TryFrom for Vec> { type Error = Error; fn try_from(params: IndexableParams) -> Result { @@ -49,12 +59,14 @@ impl TryFrom for Vec> { } } +#[cfg(feature = "mint")] impl AsRef for IndexableParams { fn as_ref(&self) -> &SubId { &self.0.id } } +#[cfg(feature = "mint")] impl Indexable for NotificationPayload { type Type = Notification; diff --git a/crates/cdk-fake-wallet/Cargo.toml b/crates/cdk-fake-wallet/Cargo.toml index 884d39e5..8807f131 100644 --- a/crates/cdk-fake-wallet/Cargo.toml +++ b/crates/cdk-fake-wallet/Cargo.toml @@ -6,19 +6,19 @@ authors = ["CDK Developers"] license = "MIT" homepage = "https://github.com/cashubtc/cdk" repository = "https://github.com/cashubtc/cdk.git" -rust-version = "1.63.0" # MSRV +rust-version = "1.75.0" # MSRV description = "CDK fake ln backend" [dependencies] -async-trait = "0.1.74" -bitcoin = { version = "0.32.2", default-features = false } -cdk = { path = "../cdk", version = "0.7.1", default-features = false, features = ["mint"] } -futures = { version = "0.3.28", default-features = false } -tokio = { version = "1", default-features = false } -tokio-util = { version = "0.7.11", default-features = false } -tracing = { version = "0.1", default-features = false, features = ["attributes", "log"] } -thiserror = "1" -serde = "1" -serde_json = "1" -lightning-invoice = { version = "0.32.0", features = ["serde", "std"] } +async-trait.workspace = true +bitcoin.workspace = true +cdk = { workspace = true, features = ["mint"] } +futures.workspace = true +tokio.workspace = true +tokio-util.workspace = true +tracing.workspace = true +thiserror.workspace = true +serde.workspace = true +serde_json.workspace = true +lightning-invoice.workspace = true tokio-stream = "0.1.15" diff --git a/crates/cdk-integration-tests/Cargo.toml b/crates/cdk-integration-tests/Cargo.toml index ce66f675..2a5c92c7 100644 --- a/crates/cdk-integration-tests/Cargo.toml +++ b/crates/cdk-integration-tests/Cargo.toml @@ -7,18 +7,18 @@ description = "Core Cashu Development Kit library implementing the Cashu protoco license = "MIT" homepage = "https://github.com/cashubtc/cdk" repository = "https://github.com/cashubtc/cdk.git" -rust-version = "1.63.0" # MSRV +rust-version = "1.75.0" # MSRV [features] http_subscription = ["cdk/http_subscription"] [dependencies] -async-trait = "0.1" -axum = "0.6.20" -rand = "0.8.5" -bip39 = { version = "2.0", features = ["rand"] } -anyhow = "1" +async-trait.workspace = true +axum.workspace = true +rand.workspace = true +bip39 = { workspace = true, features = ["rand"] } +anyhow.workspace = true cashu = { path = "../cashu", features = ["mint", "wallet"] } cdk = { path = "../cdk", features = ["mint", "wallet"] } cdk-cln = { path = "../cdk-cln" } @@ -27,42 +27,34 @@ cdk-axum = { path = "../cdk-axum" } cdk-sqlite = { path = "../cdk-sqlite" } cdk-redb = { path = "../cdk-redb" } cdk-fake-wallet = { path = "../cdk-fake-wallet" } -tower-http = { version = "0.4.4", features = ["cors"] } -futures = { version = "0.3.28", default-features = false, features = [ +futures = { workspace = true, default-features = false, features = [ "executor", ] } -once_cell = "1.19.0" -uuid = { version = "1", features = ["v4"] } -serde = "1" -serde_json = "1" +once_cell.workspace = true +uuid.workspace = true +serde.workspace = true +serde_json.workspace = true # ln-regtest-rs = { path = "../../../../ln-regtest-rs" } -ln-regtest-rs = { git = "https://github.com/thesimplekid/ln-regtest-rs", rev = "bf09ad6" } +ln-regtest-rs = { git = "https://github.com/thesimplekid/ln-regtest-rs", rev = "ed24716" } lightning-invoice = { version = "0.32.0", features = ["serde", "std"] } -tracing = { version = "0.1", default-features = false, features = [ - "attributes", - "log", -] } -tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } +tracing.workspace = true +tracing-subscriber.workspace = true +tokio-tungstenite.workspace = true +tower-http = { workspace = true, features = ["cors"] } tower-service = "0.3.3" -tokio-tungstenite = "0.24.0" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] -tokio = { version = "1", features = [ - "rt-multi-thread", - "time", - "macros", - "sync", -] } +tokio.workspace = true [target.'cfg(target_arch = "wasm32")'.dependencies] -tokio = { version = "1", features = ["rt", "macros", "sync", "time"] } +tokio = { workspace = true, features = ["rt", "macros", "sync", "time"] } getrandom = { version = "0.2", features = ["js"] } -instant = { version = "0.1", features = ["wasm-bindgen", "inaccurate"] } +instant = { workspace = true, features = ["wasm-bindgen", "inaccurate"] } [dev-dependencies] -bip39 = { version = "2.0", features = ["rand"] } -anyhow = "1" +bip39 = { workspace = true, features = ["rand"] } +anyhow.workspace = true cdk = { path = "../cdk", features = ["mint", "wallet"] } cdk-axum = { path = "../cdk-axum" } cdk-fake-wallet = { path = "../cdk-fake-wallet" } -tower-http = { version = "0.4.4", features = ["cors"] } +tower-http = { workspace = true, features = ["cors"] } diff --git a/crates/cdk-integration-tests/src/lib.rs b/crates/cdk-integration-tests/src/lib.rs index 70b47187..c2ef5401 100644 --- a/crates/cdk-integration-tests/src/lib.rs +++ b/crates/cdk-integration-tests/src/lib.rs @@ -67,7 +67,6 @@ pub async fn attempt_to_swap_pending(wallet: &Wallet) -> Result<()> { Ok(()) } -#[allow(clippy::incompatible_msrv)] pub async fn wait_for_mint_to_be_paid( wallet: &Wallet, mint_quote_id: &str, diff --git a/crates/cdk-integration-tests/tests/regtest.rs b/crates/cdk-integration-tests/tests/regtest.rs index 96a2673b..55a74aa0 100644 --- a/crates/cdk-integration-tests/tests/regtest.rs +++ b/crates/cdk-integration-tests/tests/regtest.rs @@ -110,19 +110,22 @@ async fn test_regtest_mint_melt_round_trip() -> Result<()> { let melt = wallet.melt_quote(invoice, None).await?; write - .send(Message::Text(serde_json::to_string(&json!({ - "jsonrpc": "2.0", - "id": 2, - "method": "subscribe", - "params": { - "kind": "bolt11_melt_quote", - "filters": [ - melt.id.clone(), - ], - "subId": "test-sub", - } + .send(Message::Text( + serde_json::to_string(&json!({ + "jsonrpc": "2.0", + "id": 2, + "method": "subscribe", + "params": { + "kind": "bolt11_melt_quote", + "filters": [ + melt.id.clone(), + ], + "subId": "test-sub", + } - }))?)) + }))? + .into(), + )) .await?; assert_eq!( diff --git a/crates/cdk-lnbits/Cargo.toml b/crates/cdk-lnbits/Cargo.toml index e482e34a..54f401d0 100644 --- a/crates/cdk-lnbits/Cargo.toml +++ b/crates/cdk-lnbits/Cargo.toml @@ -6,18 +6,18 @@ authors = ["CDK Developers"] license = "MIT" homepage = "https://github.com/cashubtc/cdk" repository = "https://github.com/cashubtc/cdk.git" -rust-version = "1.63.0" # MSRV +rust-version = "1.75.0" # MSRV description = "CDK ln backend for lnbits" [dependencies] -async-trait = "0.1" -anyhow = "1" -axum = "0.6.20" -bitcoin = { version = "0.32.2", default-features = false } -cdk = { path = "../cdk", version = "0.7.1", default-features = false, features = ["mint"] } -futures = { version = "0.3.28", default-features = false } -tokio = { version = "1", default-features = false } -tokio-util = { version = "0.7.11", default-features = false } -tracing = { version = "0.1", default-features = false, features = ["attributes", "log"] } -thiserror = "1" -lnbits-rs = "0.3.0" +async-trait.workspace = true +anyhow.workspace = true +axum.workspace = true +bitcoin.workspace = true +cdk = { workspace = true, features = ["mint"] } +futures.workspace = true +tokio.workspace = true +tokio-util.workspace = true +tracing.workspace = true +thiserror.workspace = true +lnbits-rs = "0.4.0" diff --git a/crates/cdk-lnbits/src/lib.rs b/crates/cdk-lnbits/src/lib.rs index a4938229..fd0c9f6c 100644 --- a/crates/cdk-lnbits/src/lib.rs +++ b/crates/cdk-lnbits/src/lib.rs @@ -83,7 +83,6 @@ impl MintLightning for LNbits { self.wait_invoice_cancel_token.cancel() } - #[allow(clippy::incompatible_msrv)] async fn wait_any_invoice( &self, ) -> Result + Send>>, Self::Err> { @@ -182,7 +181,7 @@ impl MintLightning for LNbits { ) -> Result { let pay_response = self .lnbits_api - .pay_invoice(&melt_quote.request) + .pay_invoice(&melt_quote.request, None) .await .map_err(|err| { tracing::error!("Could not pay invoice"); diff --git a/crates/cdk-lnd/Cargo.toml b/crates/cdk-lnd/Cargo.toml index 67899e31..13e39238 100644 --- a/crates/cdk-lnd/Cargo.toml +++ b/crates/cdk-lnd/Cargo.toml @@ -9,12 +9,12 @@ repository = "https://github.com/cashubtc/cdk.git" description = "CDK ln backend for lnd" [dependencies] -async-trait = "0.1" -anyhow = "1" -cdk = { path = "../cdk", version= "0.7.1", default-features = false, features = ["mint"] } +async-trait.workspace = true +anyhow.workspace = true +cdk = { workspace = true, features = ["mint"] } fedimint-tonic-lnd = "0.2.0" -futures = { version = "0.3.28", default-features = false } -tokio = { version = "1", default-features = false } -tokio-util = { version = "0.7.11", default-features = false } -tracing = { version = "0.1", default-features = false, features = ["attributes", "log"] } -thiserror = "1" +futures.workspace = true +tokio.workspace = true +tokio-util.workspace = true +tracing.workspace = true +thiserror.workspace = true diff --git a/crates/cdk-lnd/README.md b/crates/cdk-lnd/README.md index 010e5eec..26cf8b5d 100644 --- a/crates/cdk-lnd/README.md +++ b/crates/cdk-lnd/README.md @@ -1,14 +1,4 @@ ## Minimum Supported Rust Version (MSRV) -The `cdk` library should always compile with any combination of features on Rust **1.66.0**. - -To build and test with the MSRV you will need to pin the below dependency versions: - -```shell -cargo update -p home --precise 0.5.5 -cargo update -p prost --precise 0.12.3 -cargo update -p prost-types --precise 0.12.3 -cargo update -p prost-build --precise 0.12.3 -cargo update -p prost-derive --precise 0.12.3 -``` +The `cdk-lnd` library should always compile with any combination of features on Rust **1.75.0**. diff --git a/crates/cdk-mint-rpc/Cargo.toml b/crates/cdk-mint-rpc/Cargo.toml index db9f07f3..d191438e 100644 --- a/crates/cdk-mint-rpc/Cargo.toml +++ b/crates/cdk-mint-rpc/Cargo.toml @@ -7,35 +7,32 @@ description = "CDK mintd mint managment RPC client and server" license = "MIT" homepage = "https://github.com/cashubtc/cdk" repository = "https://github.com/cashubtc/cdk.git" -rust-version = "1.63.0" # MSRV +rust-version = "1.75.0" # MSRV [[bin]] name = "cdk-mint-cli" path = "src/bin/mint_rpc_cli.rs" [dependencies] -anyhow = "1" -cdk = { path = "../cdk", version = "0.7.1", default-features = false, features = [ +anyhow.workspace = true +cdk = { workspace = true, features = [ "mint", ] } -clap = { version = "~4.0.32", features = ["derive"] } -tonic = { version = "0.9", features = [ +clap.workspace = true +tonic = { version = "0.12.3", features = [ "channel", "tls", "tls-webpki-roots", ] } -tracing = { version = "0.1", default-features = false, features = [ - "attributes", - "log", -] } -tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } -tokio = { version = "1", default-features = false } -serde_json = "1" -serde = { version = "1", features = ["derive"] } -thiserror = "1" -prost = "0.11.0" -home = "0.5.5" +tracing.workspace = true +tracing-subscriber.workspace = true +tokio.workspace = true +serde_json.workspace = true +serde.workspace = true +thiserror.workspace = true +prost = "0.13.1" +home.workspace = true [build-dependencies] -tonic-build = "0.9" +tonic-build = "0.12" diff --git a/crates/cdk-mintd/Cargo.toml b/crates/cdk-mintd/Cargo.toml index 8a847c65..f5bdf1a3 100644 --- a/crates/cdk-mintd/Cargo.toml +++ b/crates/cdk-mintd/Cargo.toml @@ -7,53 +7,49 @@ license = "MIT" homepage = "https://github.com/cashubtc/cdk" repository = "https://github.com/cashubtc/cdk.git" description = "CDK mint binary" +rust-version = "1.75.0" [features] default = ["management-rpc"] swagger = ["cdk-axum/swagger", "dep:utoipa", "dep:utoipa-swagger-ui"] redis = ["cdk-axum/redis"] management-rpc = ["cdk-mint-rpc"] +# MSRV is not commited to with redb enabled +redb = ["dep:cdk-redb"] [dependencies] -anyhow = "1" -axum = "0.6.20" -cdk = { path = "../cdk", version = "0.7.1", default-features = false, features = [ +anyhow.workspace = true +async-trait.workspace = true +axum.workspace = true +cdk = { workspace = true, features = [ "mint", ] } -cdk-redb = { path = "../cdk-redb", version = "0.7.1", default-features = false, features = [ +cdk-redb = { workspace = true, features = [ + "mint", +], optional = true } +cdk-sqlite = { workspace = true, features = [ "mint", ] } -cdk-sqlite = { path = "../cdk-sqlite", version = "0.7.1", default-features = false, features = [ - "mint", -] } -cdk-cln = { path = "../cdk-cln", version = "0.7.1", default-features = false } -cdk-lnbits = { path = "../cdk-lnbits", version = "0.7.1", default-features = false } -cdk-phoenixd = { path = "../cdk-phoenixd", version = "0.7.1", default-features = false } -cdk-lnd = { path = "../cdk-lnd", version = "0.7.1", default-features = false } -cdk-fake-wallet = { path = "../cdk-fake-wallet", version = "0.7.1", default-features = false } -cdk-strike = { path = "../cdk-strike", version = "0.7.1" } -cdk-axum = { path = "../cdk-axum", version = "0.7.1", default-features = false } -cdk-mint-rpc = { path = "../cdk-mint-rpc", version = "0.7.1", default-features = false, optional = true } +cdk-cln.workspace = true +cdk-lnbits.workspace = true +cdk-phoenixd.workspace = true +cdk-lnd.workspace = true +cdk-fake-wallet.workspace = true +cdk-axum.workspace = true +cdk-mint-rpc = { workspace = true, optional = true } config = { version = "0.13.3", features = ["toml"] } -clap = { version = "~4.0.32", features = ["derive"] } -bitcoin = { version = "0.32.2", features = [ - "base64", - "serde", - "rand", - "rand-std", -] } -tokio = { version = "1", default-features = false, features = ["signal"] } -tracing = { version = "0.1", default-features = false, features = [ - "attributes", - "log", -] } -tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } -futures = { version = "0.3.28", default-features = false } -serde = { version = "1", default-features = false, features = ["derive"] } -bip39 = { version = "2.0", features = ["rand"] } -tower-http = { version = "0.4.4", features = ["cors", "compression-full"] } -lightning-invoice = { version = "0.32.0", features = ["serde", "std"] } +clap.workspace = true +bitcoin.workspace = true +tokio = { workspace = true, default-features = false, features = ["signal"] } +tracing.workspace = true +tracing-subscriber.workspace = true +futures.workspace = true +serde.workspace = true +bip39.workspace = true +tower-http = { workspace = true, features = ["compression-full", "decompression-full"] } +tower = "0.5.2" +lightning-invoice.workspace = true home = "0.5.5" -url = "2.3" -utoipa = { version = "4", optional = true } -utoipa-swagger-ui = { version = "4", features = ["axum"], optional = true } +url.workspace = true +utoipa = { workspace = true, optional = true } +utoipa-swagger-ui = { version = "9.0.0", features = ["axum"], optional = true } diff --git a/crates/cdk-mintd/src/config.rs b/crates/cdk-mintd/src/config.rs index d9c1178b..a3394ac9 100644 --- a/crates/cdk-mintd/src/config.rs +++ b/crates/cdk-mintd/src/config.rs @@ -47,7 +47,6 @@ pub enum LnBackend { #[default] None, Cln, - Strike, LNbits, FakeWallet, Phoenixd, @@ -60,7 +59,6 @@ impl std::str::FromStr for LnBackend { fn from_str(s: &str) -> Result { match s.to_lowercase().as_str() { "cln" => Ok(LnBackend::Cln), - "strike" => Ok(LnBackend::Strike), "lnbits" => Ok(LnBackend::LNbits), "fakewallet" => Ok(LnBackend::FakeWallet), "phoenixd" => Ok(LnBackend::Phoenixd), @@ -93,12 +91,6 @@ impl Default for Ln { } } -#[derive(Debug, Clone, Serialize, Deserialize, Default)] -pub struct Strike { - pub api_key: String, - pub supported_units: Option>, -} - #[derive(Debug, Clone, Serialize, Deserialize, Default)] pub struct LNbits { pub admin_api_key: String, @@ -172,6 +164,7 @@ fn default_max_delay_time() -> u64 { pub enum DatabaseEngine { #[default] Sqlite, + #[cfg(feature = "redb")] Redb, } @@ -181,6 +174,7 @@ impl std::str::FromStr for DatabaseEngine { fn from_str(s: &str) -> Result { match s.to_lowercase().as_str() { "sqlite" => Ok(DatabaseEngine::Sqlite), + #[cfg(feature = "redb")] "redb" => Ok(DatabaseEngine::Redb), _ => Err(format!("Unknown database engine: {}", s)), } @@ -199,7 +193,6 @@ pub struct Settings { pub mint_info: MintInfo, pub ln: Ln, pub cln: Option, - pub strike: Option, pub lnbits: Option, pub phoenixd: Option, pub lnd: Option, @@ -291,10 +284,6 @@ impl Settings { settings.cln.is_some(), "CLN backend requires a valid config." ), - LnBackend::Strike => assert!( - settings.strike.is_some(), - "Strike backend requires a valid config." - ), LnBackend::LNbits => assert!( settings.lnbits.is_some(), "LNbits backend requires a valid config" diff --git a/crates/cdk-mintd/src/env_vars.rs b/crates/cdk-mintd/src/env_vars.rs index 8c5e874f..f48b54b6 100644 --- a/crates/cdk-mintd/src/env_vars.rs +++ b/crates/cdk-mintd/src/env_vars.rs @@ -9,7 +9,7 @@ use cdk::nuts::CurrencyUnit; use crate::config::MintManagementRpc; use crate::config::{ Cln, Database, DatabaseEngine, FakeWallet, Info, LNbits, Ln, LnBackend, Lnd, MintInfo, - Phoenixd, Settings, Strike, + Phoenixd, Settings, }; pub const ENV_WORK_DIR: &str = "CDK_MINTD_WORK_DIR"; @@ -45,9 +45,6 @@ pub const ENV_CLN_RPC_PATH: &str = "CDK_MINTD_CLN_RPC_PATH"; pub const ENV_CLN_BOLT12: &str = "CDK_MINTD_CLN_BOLT12"; pub const ENV_CLN_FEE_PERCENT: &str = "CDK_MINTD_CLN_FEE_PERCENT"; pub const ENV_CLN_RESERVE_FEE_MIN: &str = "CDK_MINTD_CLN_RESERVE_FEE_MIN"; -// Strike -pub const ENV_STRIKE_API_KEY: &str = "CDK_MINTD_STRIKE_API_KEY"; -pub const ENV_STRIKE_SUPPORTED_UNITS: &str = "CDK_MINTD_STRIKE_SUPPORTED_UNITS"; // LND environment variables pub const ENV_LND_ADDRESS: &str = "CDK_MINTD_LND_ADDRESS"; pub const ENV_LND_CERT_FILE: &str = "CDK_MINTD_LND_CERT_FILE"; @@ -107,9 +104,6 @@ impl Settings { LnBackend::Cln => { self.cln = Some(self.cln.clone().unwrap_or_default().from_env()); } - LnBackend::Strike => { - self.strike = Some(self.strike.clone().unwrap_or_default().from_env()); - } LnBackend::LNbits => { self.lnbits = Some(self.lnbits.clone().unwrap_or_default().from_env()); } @@ -298,27 +292,6 @@ impl Cln { } } -impl Strike { - pub fn from_env(mut self) -> Self { - // API Key - if let Ok(api_key) = env::var(ENV_STRIKE_API_KEY) { - self.api_key = api_key; - } - - // Supported Units - expects comma-separated list - if let Ok(units_str) = env::var(ENV_STRIKE_SUPPORTED_UNITS) { - self.supported_units = Some( - units_str - .split(',') - .filter_map(|s| s.trim().parse().ok()) - .collect(), - ); - } - - self - } -} - impl Lnd { pub fn from_env(mut self) -> Self { if let Ok(address) = env::var(ENV_LND_ADDRESS) { diff --git a/crates/cdk-mintd/src/main.rs b/crates/cdk-mintd/src/main.rs index d5d606d2..601ee282 100644 --- a/crates/cdk-mintd/src/main.rs +++ b/crates/cdk-mintd/src/main.rs @@ -5,15 +5,13 @@ use std::collections::HashMap; use std::env; +use std::net::SocketAddr; use std::path::PathBuf; use std::str::FromStr; use std::sync::Arc; use anyhow::{anyhow, bail, Result}; -use axum::http::Request; -use axum::middleware::Next; -use axum::response::Response; -use axum::{middleware, Router}; +use axum::Router; use bip39::Mnemonic; use cdk::cdk_database::{self, MintDatabase}; use cdk::cdk_lightning; @@ -30,12 +28,15 @@ use cdk_mintd::cli::CLIArgs; use cdk_mintd::config::{self, DatabaseEngine, LnBackend}; use cdk_mintd::env_vars::ENV_WORK_DIR; use cdk_mintd::setup::LnBackendSetup; +#[cfg(feature = "redb")] use cdk_redb::MintRedbDatabase; use cdk_sqlite::MintSqliteDatabase; use clap::Parser; use tokio::sync::Notify; +use tower::ServiceBuilder; use tower_http::compression::CompressionLayer; -use tower_http::cors::CorsLayer; +use tower_http::decompression::RequestDecompressionLayer; +use tower_http::trace::TraceLayer; use tracing_subscriber::EnvFilter; #[cfg(feature = "swagger")] use utoipa::OpenApi; @@ -49,10 +50,11 @@ async fn main() -> anyhow::Result<()> { let sqlx_filter = "sqlx=warn"; let hyper_filter = "hyper=warn"; let h2_filter = "h2=warn"; + let tower_http = "tower_http=warn"; let env_filter = EnvFilter::new(format!( - "{},{},{},{}", - default_filter, sqlx_filter, hyper_filter, h2_filter + "{},{},{},{},{}", + default_filter, sqlx_filter, hyper_filter, h2_filter, tower_http )); tracing_subscriber::fmt().with_env_filter(env_filter).init(); @@ -100,6 +102,7 @@ async fn main() -> anyhow::Result<()> { Arc::new(sqlite_db) } + #[cfg(feature = "redb")] DatabaseEngine::Redb => { let redb_path = work_dir.join("cdk-mintd.redb"); Arc::new(MintRedbDatabase::new(&redb_path)?) @@ -180,29 +183,6 @@ async fn main() -> anyhow::Result<()> { mint_builder = mint_builder.add_supported_websockets(nut17_supported); } - LnBackend::Strike => { - let strike_settings = settings.clone().strike.expect("Checked on config load"); - - for unit in strike_settings - .clone() - .supported_units - .unwrap_or(vec![CurrencyUnit::Sat]) - { - let strike = strike_settings - .setup(&mut ln_routers, &settings, unit.clone()) - .await?; - - mint_builder = mint_builder.add_ln_backend( - unit.clone(), - PaymentMethod::Bolt11, - mint_melt_limits, - Arc::new(strike), - ); - let nut17_supported = SupportedMethods::new(PaymentMethod::Bolt11, unit); - - mint_builder = mint_builder.add_supported_websockets(nut17_supported); - } - } LnBackend::LNbits => { let lnbits_settings = settings.clone().lnbits.expect("Checked on config load"); let lnbits = lnbits_settings @@ -341,9 +321,12 @@ async fn main() -> anyhow::Result<()> { let mut mint_service = Router::new() .merge(v1_service) - .layer(CompressionLayer::new()) - .layer(middleware::from_fn(logging_middleware)) - .layer(CorsLayer::permissive()); + .layer( + ServiceBuilder::new() + .layer(RequestDecompressionLayer::new()) + .layer(CompressionLayer::new()), + ) + .layer(TraceLayer::new_for_http()); #[cfg(feature = "swagger")] { @@ -406,13 +389,13 @@ async fn main() -> anyhow::Result<()> { mint.set_quote_ttl(QuoteTTL::new(10_000, 10_000)).await?; } - let axum_result = axum::Server::bind( - &format!("{}:{}", listen_addr, listen_port) - .as_str() - .parse()?, - ) - .serve(mint_service.into_make_service()) - .with_graceful_shutdown(shutdown_signal()); + let socket_addr = SocketAddr::from_str(&format!("{}:{}", listen_addr, listen_port))?; + + let listener = tokio::net::TcpListener::bind(socket_addr).await?; + + tracing::debug!("listening on {}", listener.local_addr().unwrap()); + + let axum_result = axum::serve(listener, mint_service).with_graceful_shutdown(shutdown_signal()); match axum_result.await { Ok(_) => { @@ -437,29 +420,6 @@ async fn main() -> anyhow::Result<()> { Ok(()) } -/// Logs infos about the request and the response -async fn logging_middleware(req: Request, next: Next) -> Response { - let start = std::time::Instant::now(); - let path = req.uri().path().to_owned(); - let method = req.method().clone(); - - let response = next.run(req).await; - - let duration = start.elapsed(); - let status = response.status(); - let compression = response - .headers() - .get("content-encoding") - .map(|h| h.to_str().unwrap_or("none")) - .unwrap_or("none"); - - tracing::trace!( - "Request: {method} {path} | Status: {status} | Compression: {compression} | Duration: {duration:?}", - ); - - response -} - fn work_dir() -> Result { let home_dir = home::home_dir().ok_or(anyhow!("Unknown home dir"))?; let dir = home_dir.join(".cdk-mintd"); diff --git a/crates/cdk-mintd/src/setup.rs b/crates/cdk-mintd/src/setup.rs index 1e3031a5..4c23dc3a 100644 --- a/crates/cdk-mintd/src/setup.rs +++ b/crates/cdk-mintd/src/setup.rs @@ -2,7 +2,8 @@ use std::collections::{HashMap, HashSet}; use std::sync::Arc; use anyhow::{anyhow, bail}; -use axum::{async_trait, Router}; +use async_trait::async_trait; +use axum::Router; use bip39::rand::{thread_rng, Rng}; use cdk::cdk_lightning::MintLightning; use cdk::mint::FeeReserve; @@ -50,40 +51,6 @@ impl LnBackendSetup for config::Cln { } } -#[async_trait] -impl LnBackendSetup for config::Strike { - async fn setup( - &self, - routers: &mut Vec, - settings: &Settings, - unit: CurrencyUnit, - ) -> anyhow::Result { - 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( diff --git a/crates/cdk-phoenixd/Cargo.toml b/crates/cdk-phoenixd/Cargo.toml index ddb4351c..0ff7b8c0 100644 --- a/crates/cdk-phoenixd/Cargo.toml +++ b/crates/cdk-phoenixd/Cargo.toml @@ -6,19 +6,19 @@ authors = ["CDK Developers"] license = "MIT" homepage = "https://github.com/cashubtc/cdk" repository = "https://github.com/cashubtc/cdk.git" -rust-version = "1.63.0" # MSRV +rust-version = "1.75.0" # MSRV description = "CDK ln backend for phoenixd" [dependencies] -async-trait = "0.1" -anyhow = "1" -axum = "0.6.20" -bitcoin = { version = "0.32.2", default-features = false } -cdk = { path = "../cdk", version = "0.7.1", default-features = false, features = ["mint"] } -futures = { version = "0.3.28", default-features = false } -tokio = { version = "1", default-features = false } -tokio-util = { version = "0.7.11", default-features = false } -tracing = { version = "0.1", default-features = false, features = ["attributes", "log"] } -thiserror = "1" -phoenixd-rs = "0.4.0" -uuid = { version = "1", features = ["v4"] } +async-trait.workspace = true +anyhow.workspace = true +axum.workspace = true +bitcoin.workspace = true +cdk = { workspace = true, features = ["mint"] } +futures.workspace = true +tokio.workspace = true +tokio-util.workspace = true +tracing.workspace = true +thiserror.workspace = true +phoenixd-rs = "0.5.0" +uuid.workspace = true diff --git a/crates/cdk-phoenixd/src/lib.rs b/crates/cdk-phoenixd/src/lib.rs index b0993341..ba62958b 100644 --- a/crates/cdk-phoenixd/src/lib.rs +++ b/crates/cdk-phoenixd/src/lib.rs @@ -89,7 +89,6 @@ impl MintLightning for Phoenixd { self.wait_invoice_cancel_token.cancel() } - #[allow(clippy::incompatible_msrv)] async fn wait_any_invoice( &self, ) -> Result + Send>>, Self::Err> { diff --git a/crates/cdk-redb/Cargo.toml b/crates/cdk-redb/Cargo.toml index ce39c59d..1f600046 100644 --- a/crates/cdk-redb/Cargo.toml +++ b/crates/cdk-redb/Cargo.toml @@ -7,24 +7,21 @@ description = "Redb storage backend for CDK" license = "MIT" homepage = "https://github.com/cashubtc/cdk" repository = "https://github.com/cashubtc/cdk.git" -rust-version = "1.66.0" # MSRV +rust-version = "1.81.0" # MSRV # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [features] default = ["mint", "wallet"] -mint = [] -wallet = [] +mint = ["cdk-common/mint"] +wallet = ["cdk-common/wallet"] [dependencies] -async-trait = "0.1" -cdk-common = { path = "../cdk-common", version = "0.7.1" } -redb = "2.2.0" -thiserror = "1" -tracing = { version = "0.1", default-features = false, features = [ - "attributes", - "log", -] } -serde = { version = "1", default-features = false, features = ["derive"] } -serde_json = "1" -lightning-invoice = { version = "0.32.0", features = ["serde", "std"] } -uuid = { version = "1", features = ["v4", "serde"] } +async-trait.workspace = true +cdk-common.workspace = true +redb = "2.4.0" +thiserror.workspace = true +tracing.workspace = true +serde.workspace = true +serde_json.workspace = true +lightning-invoice.workspace = true +uuid.workspace = true diff --git a/crates/cdk-rexie/Cargo.toml b/crates/cdk-rexie/Cargo.toml index 71a0ddc5..f7047798 100644 --- a/crates/cdk-rexie/Cargo.toml +++ b/crates/cdk-rexie/Cargo.toml @@ -7,7 +7,7 @@ description = "Indexdb storage backend for CDK in the browser" license = "MIT" homepage = "https://github.com/cashubtc/cdk" repository = "https://github.com/cashubtc/cdk.git" -rust-version = "1.63.0" # MSRV +rust-version = "1.75.0" # MSRV # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [features] @@ -16,11 +16,11 @@ wallet = ["cdk/wallet"] [dependencies] rexie = "0.6.0" -cdk = { path = "../cdk", version = "0.7.1", default-features = false } -async-trait = "0.1.74" -tokio = { version = "1", default-features = false } -serde = { version = "1", default-features = false, features = ["derive"] } -serde_json = "1" -thiserror = "1" +cdk.workspace = true +async-trait.workspace = true +tokio.workspace = true +serde.workspace = true +serde_json.workspace = true +thiserror.workspace = true serde-wasm-bindgen = "0.6.5" web-sys = { version = "0.3.69", default-features = false, features = ["console"] } diff --git a/crates/cdk-sqlite/Cargo.toml b/crates/cdk-sqlite/Cargo.toml index 4eab96ff..f1577973 100644 --- a/crates/cdk-sqlite/Cargo.toml +++ b/crates/cdk-sqlite/Cargo.toml @@ -7,31 +7,28 @@ description = "SQLite storage backend for CDK" license = "MIT" homepage = "https://github.com/cashubtc/cdk" repository = "https://github.com/cashubtc/cdk.git" -rust-version = "1.66.0" # MSRV +rust-version = "1.75.0" # MSRV # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [features] default = ["mint", "wallet"] -mint = [] -wallet = [] +mint = ["cdk-common/mint"] +wallet = ["cdk-common/wallet"] [dependencies] -async-trait = "0.1" -cdk-common = { path = "../cdk-common", version = "0.7.1" } -bitcoin = { version = "0.32.2", default-features = false } +async-trait.workspace = true +cdk-common.workspace = true +bitcoin.workspace = true sqlx = { version = "0.6.3", default-features = false, features = [ "runtime-tokio-rustls", - "sqlite", + "sqlite", "macros", "migrate", "uuid", ] } -thiserror = "1" -tokio = { version = "1", features = ["time", "macros", "sync"] } -tracing = { version = "0.1", default-features = false, features = [ - "attributes", - "log", -] } -serde_json = "1" -lightning-invoice = { version = "0.32.0", features = ["serde", "std"] } -uuid = { version = "1", features = ["v4", "serde"] } +thiserror.workspace = true +tokio.workspace = true +tracing.workspace = true +serde_json.workspace = true +lightning-invoice.workspace = true +uuid.workspace = true diff --git a/crates/cdk-strike/Cargo.toml b/crates/cdk-strike/Cargo.toml deleted file mode 100644 index 525fdf71..00000000 --- a/crates/cdk-strike/Cargo.toml +++ /dev/null @@ -1,26 +0,0 @@ -[package] -name = "cdk-strike" -version = "0.7.1" -edition = "2021" -authors = ["CDK Developers"] -license = "MIT" -homepage = "https://github.com/cashubtc/cdk" -repository = "https://github.com/cashubtc/cdk.git" -rust-version = "1.63.0" # MSRV -description = "CDK ln backend for Strike api" - -[dependencies] -async-trait = "0.1" -anyhow = "1" -axum = "0.6.20" -bitcoin = { version = "0.32.2", default-features = false } -cdk = { path = "../cdk", version = "0.7.1", default-features = false, features = ["mint"] } -futures = { version = "0.3.28", default-features = false } -tokio = { version = "1", default-features = false } -tokio-util = { version = "0.7.11", default-features = false } -tracing = { version = "0.1", default-features = false, features = ["attributes", "log"] } -thiserror = "1" -uuid = { version = "1", features = ["v4"] } -strike-rs = "0.4.0" -# strike-rs = { path = "../../../../strike-rs" } -# strike-rs = { git = "https://github.com/thesimplekid/strike-rs.git", rev = "577ad9591" } diff --git a/crates/cdk-strike/src/error.rs b/crates/cdk-strike/src/error.rs deleted file mode 100644 index b9915d8d..00000000 --- a/crates/cdk-strike/src/error.rs +++ /dev/null @@ -1,26 +0,0 @@ -//! Error for Strike ln backend - -use thiserror::Error; - -/// Strike Error -#[derive(Debug, Error)] -pub enum Error { - /// Invoice amount not defined - #[error("Unknown invoice amount")] - UnknownInvoiceAmount, - /// Unknown invoice - #[error("Unknown invoice")] - UnknownInvoice, - /// Strikers error - #[error(transparent)] - StrikeRs(#[from] strike_rs::Error), - /// Anyhow error - #[error(transparent)] - Anyhow(#[from] anyhow::Error), -} - -impl From for cdk::cdk_lightning::Error { - fn from(e: Error) -> Self { - Self::Lightning(Box::new(e)) - } -} diff --git a/crates/cdk-strike/src/lib.rs b/crates/cdk-strike/src/lib.rs deleted file mode 100644 index d5533263..00000000 --- a/crates/cdk-strike/src/lib.rs +++ /dev/null @@ -1,381 +0,0 @@ -//! CDK lightning backend for Strike - -#![warn(missing_docs)] -#![warn(rustdoc::bare_urls)] - -use std::pin::Pin; -use std::sync::atomic::{AtomicBool, Ordering}; -use std::sync::Arc; - -use anyhow::{anyhow, bail}; -use async_trait::async_trait; -use axum::Router; -use cdk::amount::Amount; -use cdk::cdk_lightning::{ - self, CreateInvoiceResponse, MintLightning, PayInvoiceResponse, PaymentQuoteResponse, Settings, -}; -use cdk::nuts::{CurrencyUnit, MeltQuoteBolt11Request, MeltQuoteState, MintQuoteState}; -use cdk::util::unix_time; -use cdk::{mint, Bolt11Invoice}; -use error::Error; -use futures::stream::StreamExt; -use futures::Stream; -use strike_rs::{ - Amount as StrikeAmount, Currency as StrikeCurrencyUnit, InvoiceRequest, InvoiceState, - PayInvoiceQuoteRequest, Strike as StrikeApi, -}; -use tokio::sync::Mutex; -use tokio_util::sync::CancellationToken; -use uuid::Uuid; - -pub mod error; - -/// Strike -#[derive(Clone)] -pub struct Strike { - strike_api: StrikeApi, - unit: CurrencyUnit, - receiver: Arc>>>, - webhook_url: String, - wait_invoice_cancel_token: CancellationToken, - wait_invoice_is_active: Arc, -} - -impl Strike { - /// Create new [`Strike`] wallet - pub async fn new( - api_key: String, - unit: CurrencyUnit, - receiver: Arc>>>, - webhook_url: String, - ) -> Result { - let strike = StrikeApi::new(&api_key, None)?; - Ok(Self { - strike_api: strike, - receiver, - unit, - webhook_url, - wait_invoice_cancel_token: CancellationToken::new(), - wait_invoice_is_active: Arc::new(AtomicBool::new(false)), - }) - } -} - -#[async_trait] -impl MintLightning for Strike { - type Err = cdk_lightning::Error; - - fn get_settings(&self) -> Settings { - Settings { - mpp: false, - unit: self.unit.clone(), - invoice_description: true, - } - } - - fn is_wait_invoice_active(&self) -> bool { - self.wait_invoice_is_active.load(Ordering::SeqCst) - } - - fn cancel_wait_invoice(&self) { - self.wait_invoice_cancel_token.cancel() - } - - #[allow(clippy::incompatible_msrv)] - async fn wait_any_invoice( - &self, - ) -> Result + Send>>, Self::Err> { - self.strike_api - .subscribe_to_invoice_webhook(self.webhook_url.clone()) - .await?; - - let receiver = self - .receiver - .lock() - .await - .take() - .ok_or(anyhow!("No receiver"))?; - - let strike_api = self.strike_api.clone(); - let cancel_token = self.wait_invoice_cancel_token.clone(); - - Ok(futures::stream::unfold( - ( - receiver, - strike_api, - cancel_token, - Arc::clone(&self.wait_invoice_is_active), - ), - |(mut receiver, strike_api, cancel_token, is_active)| async move { - tokio::select! { - - _ = cancel_token.cancelled() => { - // Stream is cancelled - is_active.store(false, Ordering::SeqCst); - tracing::info!("Waiting for phonixd invoice ending"); - None - } - - msg_option = receiver.recv() => { - match msg_option { - Some(msg) => { - let check = strike_api.get_incoming_invoice(&msg).await; - - match check { - Ok(state) => { - if state.state == InvoiceState::Paid { - Some((msg, (receiver, strike_api, cancel_token, is_active))) - } else { - None - } - } - _ => None, - } - } - None => None, - } - - } - } - }, - ) - .boxed()) - } - - async fn get_payment_quote( - &self, - melt_quote_request: &MeltQuoteBolt11Request, - ) -> Result { - if melt_quote_request.unit != self.unit { - return Err(Self::Err::Anyhow(anyhow!("Unsupported unit"))); - } - - let source_currency = match melt_quote_request.unit { - CurrencyUnit::Sat => StrikeCurrencyUnit::BTC, - CurrencyUnit::Msat => StrikeCurrencyUnit::BTC, - CurrencyUnit::Usd => StrikeCurrencyUnit::USD, - CurrencyUnit::Eur => StrikeCurrencyUnit::EUR, - _ => return Err(Self::Err::UnsupportedUnit), - }; - - let payment_quote_request = PayInvoiceQuoteRequest { - ln_invoice: melt_quote_request.request.to_string(), - source_currency, - }; - - let quote = self.strike_api.payment_quote(payment_quote_request).await?; - - let fee = from_strike_amount(quote.lightning_network_fee, &melt_quote_request.unit)?; - - let amount = from_strike_amount(quote.amount, &melt_quote_request.unit)?.into(); - - Ok(PaymentQuoteResponse { - request_lookup_id: quote.payment_quote_id, - amount, - fee: fee.into(), - state: MeltQuoteState::Unpaid, - }) - } - - async fn pay_invoice( - &self, - melt_quote: mint::MeltQuote, - _partial_msats: Option, - _max_fee_msats: Option, - ) -> Result { - let pay_response = self - .strike_api - .pay_quote(&melt_quote.request_lookup_id) - .await?; - - let state = match pay_response.state { - InvoiceState::Paid => MeltQuoteState::Paid, - InvoiceState::Unpaid => MeltQuoteState::Unpaid, - InvoiceState::Completed => MeltQuoteState::Paid, - InvoiceState::Pending => MeltQuoteState::Pending, - }; - - let total_spent = from_strike_amount(pay_response.total_amount, &melt_quote.unit)?.into(); - - Ok(PayInvoiceResponse { - payment_lookup_id: pay_response.payment_id, - payment_preimage: None, - status: state, - total_spent, - unit: melt_quote.unit, - }) - } - - async fn create_invoice( - &self, - amount: Amount, - _unit: &CurrencyUnit, - description: String, - unix_expiry: u64, - ) -> Result { - let time_now = unix_time(); - assert!(unix_expiry > time_now); - let request_lookup_id = Uuid::new_v4(); - - let invoice_request = InvoiceRequest { - correlation_id: Some(request_lookup_id.to_string()), - amount: to_strike_unit(amount, &self.unit)?, - description: Some(description), - }; - - let create_invoice_response = self.strike_api.create_invoice(invoice_request).await?; - - let quote = self - .strike_api - .invoice_quote(&create_invoice_response.invoice_id) - .await?; - - let request: Bolt11Invoice = quote.ln_invoice.parse()?; - let expiry = request.expires_at().map(|t| t.as_secs()); - - Ok(CreateInvoiceResponse { - request_lookup_id: create_invoice_response.invoice_id, - request: quote.ln_invoice.parse()?, - expiry, - }) - } - - async fn check_incoming_invoice_status( - &self, - request_lookup_id: &str, - ) -> Result { - let invoice = self - .strike_api - .get_incoming_invoice(request_lookup_id) - .await?; - - let state = match invoice.state { - InvoiceState::Paid => MintQuoteState::Paid, - InvoiceState::Unpaid => MintQuoteState::Unpaid, - InvoiceState::Completed => MintQuoteState::Paid, - InvoiceState::Pending => MintQuoteState::Pending, - }; - - Ok(state) - } - - async fn check_outgoing_payment( - &self, - payment_id: &str, - ) -> Result { - let invoice = self.strike_api.get_outgoing_payment(payment_id).await; - - let pay_invoice_response = match invoice { - Ok(invoice) => { - let state = match invoice.state { - InvoiceState::Paid => MeltQuoteState::Paid, - InvoiceState::Unpaid => MeltQuoteState::Unpaid, - InvoiceState::Completed => MeltQuoteState::Paid, - InvoiceState::Pending => MeltQuoteState::Pending, - }; - - PayInvoiceResponse { - payment_lookup_id: invoice.payment_id, - payment_preimage: None, - status: state, - total_spent: from_strike_amount(invoice.total_amount, &self.unit)?.into(), - unit: self.unit.clone(), - } - } - Err(err) => match err { - strike_rs::Error::NotFound => PayInvoiceResponse { - payment_lookup_id: payment_id.to_string(), - payment_preimage: None, - status: MeltQuoteState::Unknown, - total_spent: Amount::ZERO, - unit: self.unit.clone(), - }, - _ => { - return Err(Error::from(err).into()); - } - }, - }; - - Ok(pay_invoice_response) - } -} - -impl Strike { - /// Create invoice webhook - pub async fn create_invoice_webhook( - &self, - webhook_endpoint: &str, - sender: tokio::sync::mpsc::Sender, - ) -> anyhow::Result { - let subs = self.strike_api.get_current_subscriptions().await?; - - tracing::debug!("Got {} current subscriptions", subs.len()); - - for sub in subs { - tracing::info!("Deleting webhook: {}", &sub.id); - if let Err(err) = self.strike_api.delete_subscription(&sub.id).await { - tracing::error!("Error deleting webhook subscription: {} {}", sub.id, err); - } - } - - self.strike_api - .create_invoice_webhook_router(webhook_endpoint, sender) - .await - } -} - -pub(crate) fn from_strike_amount( - strike_amount: StrikeAmount, - target_unit: &CurrencyUnit, -) -> anyhow::Result { - match target_unit { - CurrencyUnit::Sat => strike_amount.to_sats(), - CurrencyUnit::Msat => Ok(strike_amount.to_sats()? * 1000), - CurrencyUnit::Usd => { - if strike_amount.currency == StrikeCurrencyUnit::USD { - Ok((strike_amount.amount * 100.0).round() as u64) - } else { - bail!("Could not convert strike USD"); - } - } - CurrencyUnit::Eur => { - if strike_amount.currency == StrikeCurrencyUnit::EUR { - Ok((strike_amount.amount * 100.0).round() as u64) - } else { - bail!("Could not convert to EUR"); - } - } - _ => bail!("Unsupported unit"), - } -} - -pub(crate) fn to_strike_unit( - amount: T, - current_unit: &CurrencyUnit, -) -> anyhow::Result -where - T: Into, -{ - let amount = amount.into(); - match current_unit { - CurrencyUnit::Sat => Ok(StrikeAmount::from_sats(amount)), - CurrencyUnit::Msat => Ok(StrikeAmount::from_sats(amount / 1000)), - CurrencyUnit::Usd => { - let dollars = (amount as f64 / 100_f64) * 100.0; - - Ok(StrikeAmount { - currency: StrikeCurrencyUnit::USD, - amount: dollars.round() / 100.0, - }) - } - CurrencyUnit::Eur => { - let euro = (amount as f64 / 100_f64) * 100.0; - - Ok(StrikeAmount { - currency: StrikeCurrencyUnit::EUR, - amount: euro.round() / 100.0, - }) - } - _ => bail!("Unsupported unit"), - } -} diff --git a/crates/cdk/Cargo.toml b/crates/cdk/Cargo.toml index b239c9a9..bd0f8373 100644 --- a/crates/cdk/Cargo.toml +++ b/crates/cdk/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "cdk" -version = "0.7.1" +version = "0.7.2" edition = "2021" authors = ["CDK Developers"] description = "Core Cashu Development Kit library implementing the Cashu protocol" homepage = "https://github.com/cashubtc/cdk" repository = "https://github.com/cashubtc/cdk.git" -rust-version = "1.63.0" # MSRV +rust-version = "1.75.0" # MSRV license = "MIT" @@ -21,63 +21,45 @@ http_subscription = [] [dependencies] -cdk-common = { path = "../cdk-common", version = "0.7.1" } -cbor-diag = "0.1.12" -async-trait = "0.1" -anyhow = { version = "1.0.43", features = ["backtrace"] } -bitcoin = { version = "0.32.2", features = [ - "base64", - "serde", - "rand", - "rand-std", -] } -ciborium = { version = "0.2.2", default-features = false, features = ["std"] } -lightning-invoice = { version = "0.32.0", features = ["serde", "std"] } +cdk-common.workspace = true +cbor-diag.workspace = true +async-trait.workspace = true +anyhow.workspace = true +bitcoin.workspace = true +ciborium.workspace = true +lightning-invoice.workspace = true regex = "1" -reqwest = { version = "0.12", default-features = false, features = [ - "json", - "rustls-tls", - "rustls-tls-native-roots", - "socks", - "zstd", - "brotli", - "gzip", - "deflate", -], optional = true } -serde = { version = "1", default-features = false, features = ["derive"] } -serde_json = "1" -serde_with = "3" -tracing = { version = "0.1", default-features = false, features = [ - "attributes", - "log", -] } -thiserror = "1" -futures = { version = "0.3.28", default-features = false, optional = true, features = [ - "alloc", -] } -url = "2.3" -utoipa = { version = "4", optional = true } -uuid = { version = "=1.12.1", features = ["v4", "serde"] } +reqwest = { workspace = true, optional = true } +serde.workspace = true +serde_json.workspace = true +serde_with.workspace = true +tracing.workspace = true +thiserror.workspace = true +futures = { workspace = true, optional = true, features = ["alloc"] } +url.workspace = true +utoipa = { workspace = true, optional = true } +uuid.workspace = true # -Z minimal-versions sync_wrapper = "0.1.2" bech32 = "0.9.1" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] -tokio = { version = "1.21", features = [ +tokio = { workspace = true, features = [ "rt-multi-thread", "time", "macros", "sync", ] } getrandom = { version = "0.2" } -tokio-tungstenite = { version = "0.19.0", features = [ +tokio-tungstenite = { workspace = true, features = [ "rustls", "rustls-tls-native-roots", + "connect" ] } [target.'cfg(target_arch = "wasm32")'.dependencies] -tokio = { version = "1.21", features = ["rt", "macros", "sync", "time"] } +tokio = { workspace = true, features = ["rt", "macros", "sync", "time"] } getrandom = { version = "0.2", features = ["js"] } [[example]] @@ -98,9 +80,9 @@ required-features = ["wallet"] [dev-dependencies] rand = "0.8.5" -bip39 = "2.0" -tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } -cdk-sqlite = { path = "../cdk-sqlite" } +cdk-sqlite.workspace = true +bip39.workspace = true +tracing-subscriber.workspace = true criterion = "0.5.1" [[bench]] diff --git a/crates/cdk/src/lib.rs b/crates/cdk/src/lib.rs index fb2e34ce..238ce5b3 100644 --- a/crates/cdk/src/lib.rs +++ b/crates/cdk/src/lib.rs @@ -5,7 +5,11 @@ pub mod cdk_database { //! CDK Database - pub use cdk_common::database::{Error, MintDatabase, WalletDatabase}; + pub use cdk_common::database::Error; + #[cfg(feature = "mint")] + pub use cdk_common::database::MintDatabase; + #[cfg(feature = "wallet")] + pub use cdk_common::database::WalletDatabase; } #[cfg(feature = "mint")] @@ -20,9 +24,11 @@ pub mod pub_sub; pub use cdk_common::{ amount, common as types, dhke, error::{self, Error}, - lightning as cdk_lightning, lightning_invoice, mint_url, nuts, secret, subscription, util, ws, - Amount, Bolt11Invoice, + lightning_invoice, mint_url, nuts, secret, util, ws, Amount, Bolt11Invoice, }; +#[cfg(feature = "mint")] +#[doc(hidden)] +pub use cdk_common::{lightning as cdk_lightning, subscription}; pub mod fees; diff --git a/crates/cdk/src/mint/melt.rs b/crates/cdk/src/mint/melt.rs index 6a553683..03be9746 100644 --- a/crates/cdk/src/mint/melt.rs +++ b/crates/cdk/src/mint/melt.rs @@ -370,7 +370,7 @@ impl Mint { if let Ok(Some(quote)) = self.localstore.get_melt_quote(&melt_request.quote).await { self.pubsub_manager - .melt_quote_status("e, None, None, MeltQuoteState::Unpaid); + .melt_quote_status(quote, None, None, MeltQuoteState::Unpaid); } for public_key in input_ys { diff --git a/crates/cdk/src/mint/mod.rs b/crates/cdk/src/mint/mod.rs index caee81d0..e1a83631 100644 --- a/crates/cdk/src/mint/mod.rs +++ b/crates/cdk/src/mint/mod.rs @@ -139,8 +139,6 @@ impl Mint { /// Wait for any invoice to be paid /// For each backend starts a task that waits for any invoice to be paid /// Once invoice is paid mint quote status is updated - #[allow(clippy::incompatible_msrv)] - // Clippy thinks select is not stable but it compiles fine on MSRV (1.63.0) pub async fn wait_for_paid_invoices(&self, shutdown: Arc) -> Result<(), Error> { let mint_arc = Arc::new(self.clone()); diff --git a/crates/cdk/src/wallet/subscription/http.rs b/crates/cdk/src/wallet/subscription/http.rs index d77a852e..a692d627 100644 --- a/crates/cdk/src/wallet/subscription/http.rs +++ b/crates/cdk/src/wallet/subscription/http.rs @@ -70,7 +70,6 @@ async fn convert_subscription( Some(()) } -#[allow(clippy::incompatible_msrv)] #[inline] pub async fn http_main>( initial_state: S, diff --git a/crates/cdk/src/wallet/subscription/mod.rs b/crates/cdk/src/wallet/subscription/mod.rs index 31544dd1..65c96860 100644 --- a/crates/cdk/src/wallet/subscription/mod.rs +++ b/crates/cdk/src/wallet/subscription/mod.rs @@ -290,7 +290,6 @@ impl SubscriptionClient { /// /// This is a WebSocket based subscription, where the client will connect to /// the server and stay there idle waiting for server-side notifications - #[allow(clippy::incompatible_msrv)] #[cfg(all( not(feature = "http_subscription"), feature = "mint", diff --git a/crates/cdk/src/wallet/subscription/ws.rs b/crates/cdk/src/wallet/subscription/ws.rs index f90cbe06..6e5fd450 100644 --- a/crates/cdk/src/wallet/subscription/ws.rs +++ b/crates/cdk/src/wallet/subscription/ws.rs @@ -34,7 +34,6 @@ async fn fallback_to_http>( .await } -#[allow(clippy::incompatible_msrv)] #[inline] pub async fn ws_main( http_client: Arc, @@ -131,7 +130,7 @@ pub async fn ws_main( .get(sub_id) .map(|(_, params)| get_sub_request(params.clone())) { - let _ = write.send(Message::Text(req)).await; + let _ = write.send(Message::Text(req.into())).await; subscription_requests.insert(req_id); } } @@ -192,7 +191,7 @@ pub async fn ws_main( tracing::debug!("Subscribing to {:?}", sub.1); active_subscriptions.insert(subid, sub.0.clone()); if let Some((req_id, json)) = get_sub_request(sub.1.clone()) { - let _ = write.send(Message::Text(json)).await; + let _ = write.send(Message::Text(json.into())).await; subscription_requests.insert(req_id); } }, @@ -203,7 +202,7 @@ pub async fn ws_main( } tracing::debug!("Unsubscribing from {:?}", subid); if let Some(json) = get_unsub_request(subid) { - let _ = write.send(Message::Text(json)).await; + let _ = write.send(Message::Text(json.into())).await; } } } diff --git a/flake.nix b/flake.nix index eaa72fbd..fed0024b 100644 --- a/flake.nix +++ b/flake.nix @@ -55,13 +55,7 @@ }; # MSRV stable - msrv_toolchain = pkgs.rust-bin.stable."1.63.0".default.override { - targets = [ "wasm32-unknown-unknown" ]; # wasm - }; - - - # DB MSRV stable - db_msrv_toolchain = pkgs.rust-bin.stable."1.66.0".default.override { + msrv_toolchain = pkgs.rust-bin.stable."1.75.0".default.override { targets = [ "wasm32-unknown-unknown" ]; # wasm }; @@ -86,6 +80,7 @@ clightning bitcoind sqlx-cli + cargo-outdated # Needed for github ci libz @@ -232,29 +227,16 @@ msrv = pkgs.mkShell ({ shellHook = " ${_shellHook} - cargo update -p half --precise 2.2.1 - cargo update -p tokio --precise 1.38.1 - cargo update -p tokio-util --precise 0.7.11 - cargo update -p tokio-stream --precise 0.1.15 - cargo update -p reqwest --precise 0.12.4 - cargo update -p serde_with --precise 3.1.0 - cargo update -p regex --precise 1.9.6 - cargo update -p backtrace --precise 0.3.58 + cargo update cargo update -p async-compression --precise 0.4.3 - cargo update -p zstd-sys --precise 2.0.8+zstd.1.5.5 - cargo update -p clap_lex --precise 0.3.0 - cargo update -p regex --precise 1.9.6 - cargo update -p petgraph --precise 0.6.2 - cargo update -p hashbrown@0.15.2 --precise 0.15.0 - cargo update -p async-stream --precise 0.3.5 cargo update -p home --precise 0.5.5 + cargo update -p zerofrom --precise 0.1.5 + + cargo update -p url --precise 2.5.2 # For wasm32-unknown-unknown target - cargo update -p bumpalo --precise 3.12.0 - cargo update -p moka --precise 0.11.1 cargo update -p triomphe --precise 0.1.11 - cargo update -p url --precise 2.5.2 "; buildInputs = buildInputs ++ WASMInputs ++ [ msrv_toolchain ]; @@ -268,28 +250,6 @@ } // envVars); - db_shell = pkgs.mkShell ({ - shellHook = '' - ${_shellHook} - cargo update -p half --precise 2.2.1 - cargo update -p home --precise 0.5.5 - cargo update -p tokio --precise 1.38.1 - cargo update -p tokio-stream --precise 0.1.15 - cargo update -p tokio-util --precise 0.7.11 - cargo update -p serde_with --precise 3.1.0 - cargo update -p reqwest --precise 0.12.4 - cargo update -p url --precise 2.5.2 - cargo update -p allocator-api2 --precise 0.2.18 - cargo update -p async-compression --precise 0.4.3 - cargo update -p zstd-sys --precise 2.0.8+zstd.1.5.5 - cargo update -p redb --precise 2.2.0 - ''; - buildInputs = buildInputs ++ WASMInputs ++ [ db_msrv_toolchain ]; - inherit nativeBuildInputs; - } // envVars); - - - nightly = pkgs.mkShell ({ shellHook = '' ${_shellHook} @@ -305,7 +265,7 @@ in { - inherit msrv stable nightly db_shell; + inherit msrv stable nightly; default = stable; }; } diff --git a/misc/fake_itests.sh b/misc/fake_itests.sh index 633b0149..2762ca24 100755 --- a/misc/fake_itests.sh +++ b/misc/fake_itests.sh @@ -51,7 +51,7 @@ export CDK_MINTD_DATABASE=$MINT_DATABASE; echo "Starting fake mintd"; -cargo run --bin cdk-mintd & +cargo run --bin cdk-mintd --features "redb" & cdk_mintd_pid=$! URL="http://$cdk_itests_mint_addr:$cdk_itests_mint_port/v1/info" diff --git a/misc/itests.sh b/misc/itests.sh index abaf75a3..46668d2c 100755 --- a/misc/itests.sh +++ b/misc/itests.sh @@ -87,7 +87,7 @@ export CDK_MINTD_DATABASE=$MINT_DATABASE; export RUST_BACKTRACE=1 echo "Starting cln mintd"; -cargo run --bin cdk-mintd & +cargo run --bin cdk-mintd --features "redb" & cdk_mintd_pid=$! @@ -138,7 +138,7 @@ export CDK_MINTD_LN_BACKEND="lnd"; export CDK_MINTD_MNEMONIC="eye survey guilt napkin crystal cup whisper salt luggage manage unveil loyal"; echo "Starting lnd mintd"; -cargo run --bin cdk-mintd & +cargo run --bin cdk-mintd --features "redb" & cdk_mintd_lnd_pid=$! URL="http://$cdk_itests_mint_addr:$cdk_itests_mint_port_1/v1/info"