Procházet zdrojové kódy

fix clippy deny unwraps (#1392)

---------

Co-authored-by: Cesar Rodas <cesar@rodasm.com.py>
tsk před 1 měsícem
rodič
revize
53ed7cab3d
75 změnil soubory, kde provedl 291 přidání a 203 odebrání
  1. 12 12
      Cargo.toml
  2. 3 0
      crates/cashu/Cargo.toml
  3. 0 2
      crates/cashu/src/lib.rs
  4. 2 2
      crates/cashu/src/nuts/nut00/mod.rs
  5. 1 1
      crates/cashu/src/nuts/nut00/token.rs
  6. 4 6
      crates/cashu/src/nuts/nut10.rs
  7. 2 3
      crates/cashu/src/nuts/nut11/mod.rs
  8. 1 1
      crates/cashu/src/nuts/nut14/mod.rs
  9. 1 1
      crates/cashu/src/nuts/nut18/secret.rs
  10. 1 4
      crates/cashu/src/nuts/nut23.rs
  11. 3 0
      crates/cdk-axum/Cargo.toml
  12. 12 12
      crates/cdk-axum/src/lib.rs
  13. 3 0
      crates/cdk-cli/Cargo.toml
  14. 2 1
      crates/cdk-cli/src/main.rs
  15. 4 1
      crates/cdk-cli/src/sub_commands/burn.rs
  16. 1 1
      crates/cdk-cli/src/sub_commands/pay_request.rs
  17. 13 14
      crates/cdk-cli/src/sub_commands/send.rs
  18. 3 0
      crates/cdk-cln/Cargo.toml
  19. 0 2
      crates/cdk-cln/src/lib.rs
  20. 3 0
      crates/cdk-common/Cargo.toml
  21. 1 0
      crates/cdk-common/src/database/mint/test/mod.rs
  22. 0 2
      crates/cdk-common/src/lib.rs
  23. 3 0
      crates/cdk-fake-wallet/Cargo.toml
  24. 6 14
      crates/cdk-fake-wallet/src/lib.rs
  25. 3 0
      crates/cdk-ffi/Cargo.toml
  26. 2 1
      crates/cdk-ffi/src/multi_mint_wallet.rs
  27. 2 2
      crates/cdk-ffi/src/types/keys.rs
  28. 10 0
      crates/cdk-integration-tests/Cargo.toml
  29. 3 0
      crates/cdk-ldk-node/Cargo.toml
  30. 0 2
      crates/cdk-ldk-node/src/lib.rs
  31. 22 22
      crates/cdk-ldk-node/src/web/handlers/channels.rs
  32. 8 7
      crates/cdk-ldk-node/src/web/handlers/invoices.rs
  33. 12 12
      crates/cdk-ldk-node/src/web/handlers/onchain.rs
  34. 14 14
      crates/cdk-ldk-node/src/web/handlers/payments.rs
  35. 7 2
      crates/cdk-ldk-node/src/web/static_files.rs
  36. 3 0
      crates/cdk-lnbits/Cargo.toml
  37. 0 2
      crates/cdk-lnbits/src/lib.rs
  38. 3 0
      crates/cdk-lnd/Cargo.toml
  39. 2 0
      crates/cdk-lnd/build.rs
  40. 2 5
      crates/cdk-lnd/src/lib.rs
  41. 3 0
      crates/cdk-mint-rpc/Cargo.toml
  42. 2 0
      crates/cdk-mint-rpc/build.rs
  43. 1 1
      crates/cdk-mint-rpc/src/bin/mint_rpc_cli.rs
  44. 1 2
      crates/cdk-mint-rpc/src/lib.rs
  45. 3 0
      crates/cdk-mintd/Cargo.toml
  46. 2 0
      crates/cdk-mintd/build.rs
  47. 8 3
      crates/cdk-mintd/src/lib.rs
  48. 0 2
      crates/cdk-mintd/src/main.rs
  49. 3 0
      crates/cdk-payment-processor/Cargo.toml
  50. 2 0
      crates/cdk-payment-processor/build.rs
  51. 0 2
      crates/cdk-payment-processor/src/lib.rs
  52. 3 4
      crates/cdk-payment-processor/src/proto/server.rs
  53. 3 0
      crates/cdk-postgres/Cargo.toml
  54. 3 0
      crates/cdk-redb/Cargo.toml
  55. 0 2
      crates/cdk-redb/src/lib.rs
  56. 4 5
      crates/cdk-redb/src/wallet/mod.rs
  57. 3 0
      crates/cdk-signatory/Cargo.toml
  58. 3 1
      crates/cdk-signatory/build.rs
  59. 2 2
      crates/cdk-signatory/src/bin/cli/mod.rs
  60. 2 2
      crates/cdk-signatory/src/bin/signatory.rs
  61. 3 0
      crates/cdk-sql-common/Cargo.toml
  62. 2 0
      crates/cdk-sql-common/build.rs
  63. 0 3
      crates/cdk-sql-common/src/lib.rs
  64. 3 2
      crates/cdk-sql-common/src/macros.rs
  65. 4 2
      crates/cdk-sql-common/src/mint/mod.rs
  66. 36 7
      crates/cdk-sql-common/src/stmt.rs
  67. 7 5
      crates/cdk-sql-common/src/wallet/mod.rs
  68. 3 0
      crates/cdk-sqlite/Cargo.toml
  69. 0 3
      crates/cdk-sqlite/src/lib.rs
  70. 3 0
      crates/cdk/Cargo.toml
  71. 0 2
      crates/cdk/src/lib.rs
  72. 1 1
      crates/cdk/src/mint/issue/mod.rs
  73. 1 1
      crates/cdk/src/wallet/melt/melt_bolt12.rs
  74. 5 1
      crates/cdk/src/wallet/mint_connector/http_client.rs
  75. 1 2
      crates/cdk/src/wallet/swap.rs

+ 12 - 12
Cargo.toml

@@ -6,21 +6,21 @@ resolver = "2"
 
 [workspace.lints.rust]
 unsafe_code = "forbid"
-unreachable_pub = "warn"
-missing_debug_implementations = "warn"
+# unreachable_pub = "warn"
+# missing_debug_implementations = "warn"
 
 [workspace.lints.clippy]
-pedantic = "warn"
-unwrap_used = "warn"
-clone_on_ref_ptr = "warn"
-missing_errors_doc = "warn"
-missing_panics_doc = "warn"
+# pedantic = { level = "warn", priority = -1 }
+unwrap_used = "deny"
+# clone_on_ref_ptr = "warn"
+# missing_errors_doc = "warn"
+# missing_panics_doc = "warn"
 missing_safety_doc = "warn"
-nursery = "warn"
-redundant_else = "warn"
-redundant_closure_for_method_calls = "warn"
-unneeded_field_pattern = "warn"
-use_debug = "warn"
+# nursery = { level = "warn", priority = -1 }
+# redundant_else = "warn"
+# redundant_closure_for_method_calls = "warn"
+# unneeded_field_pattern = "warn"
+# use_debug = "warn"
 large_enum_variant = "warn"
 
 [workspace.lints.rustdoc]

+ 3 - 0
crates/cashu/Cargo.toml

@@ -44,3 +44,6 @@ uuid = { workspace = true, features = ["js"], optional = true }
 
 [dev-dependencies]
 bip39.workspace = true
+
+[lints]
+workspace = true

+ 0 - 2
crates/cashu/src/lib.rs

@@ -1,6 +1,4 @@
 #![doc = include_str!("../README.md")]
-#![warn(missing_docs)]
-#![warn(rustdoc::bare_urls)]
 
 pub mod amount;
 pub mod dhke;

+ 2 - 2
crates/cashu/src/nuts/nut00/mod.rs

@@ -135,7 +135,7 @@ fn total_amount<'a, I: Iterator<Item = &'a Proof>>(proofs: I) -> Result<Amount,
 }
 
 fn ys<'a, I: Iterator<Item = &'a Proof>>(proofs: I) -> Result<Vec<PublicKey>, Error> {
-    proofs.map(|p| p.y()).collect::<Result<Vec<PublicKey>, _>>()
+    proofs.map(Proof::y).collect::<Result<Vec<PublicKey>, _>>()
 }
 
 /// NUT00 Error
@@ -447,11 +447,11 @@ impl From<Proof> for ProofV4 {
     fn from(proof: Proof) -> ProofV4 {
         let Proof {
             amount,
-            keyset_id: _,
             secret,
             c,
             witness,
             dleq,
+            ..
         } = proof;
         ProofV4 {
             amount,

+ 1 - 1
crates/cashu/src/nuts/nut00/token.rs

@@ -611,7 +611,7 @@ impl TokenV4Token {
         let short_id = ShortKeysetId::from(keyset_id);
         Self {
             keyset_id: short_id,
-            proofs: proofs.into_iter().map(|p| p.into()).collect(),
+            proofs: proofs.into_iter().map(Into::into).collect(),
         }
     }
 }

+ 4 - 6
crates/cashu/src/nuts/nut10.rs

@@ -71,7 +71,7 @@ impl SecretData {
         Self {
             nonce,
             data: data.into(),
-            tags: tags.map(|v| v.into()),
+            tags: tags.map(Into::into),
         }
     }
 
@@ -302,12 +302,10 @@ pub trait SpendingConditionVerification {
     fn verify_all_inputs_match_for_sig_all(&self) -> Result<(), super::nut11::Error> {
         let inputs = self.inputs();
 
-        if inputs.is_empty() {
-            return Err(super::nut11::Error::SpendConditionsNotMet);
-        }
-
         // Get first input's properties
-        let first_input = inputs.first().unwrap();
+        let first_input = inputs
+            .first()
+            .ok_or(super::nut11::Error::SpendConditionsNotMet)?;
         let first_secret = Secret::try_from(&first_input.secret)
             .map_err(|_| super::nut11::Error::IncorrectSecretKind)?;
         let first_kind = first_secret.kind();

+ 2 - 3
crates/cashu/src/nuts/nut11/mod.rs

@@ -531,9 +531,8 @@ impl TryFrom<Vec<Vec<String>>> for Conditions {
     fn try_from(tags: Vec<Vec<String>>) -> Result<Conditions, Self::Error> {
         let tags: HashMap<TagKind, Tag> = tags
             .into_iter()
-            .map(|t| Tag::try_from(t).unwrap())
-            .map(|t| (t.kind(), t))
-            .collect();
+            .map(|t| Tag::try_from(t).map(|tag| (tag.kind(), tag)))
+            .collect::<Result<_, _>>()?;
 
         let pubkeys = match tags.get(&TagKind::Pubkeys) {
             Some(Tag::PubKeys(pubkeys)) => Some(pubkeys.clone()),

+ 1 - 1
crates/cashu/src/nuts/nut14/mod.rs

@@ -179,7 +179,7 @@ impl Proof {
         let signatures = self
             .witness
             .as_ref()
-            .map(|w| w.signatures())
+            .map(super::nut00::Witness::signatures)
             .unwrap_or_default();
 
         self.witness = Some(Witness::HTLCWitness(HTLCWitness {

+ 1 - 1
crates/cashu/src/nuts/nut18/secret.rs

@@ -28,7 +28,7 @@ impl Nut10SecretRequest {
         Self {
             kind,
             data: data.into(),
-            tags: tags.map(|v| v.into()),
+            tags: tags.map(Into::into),
         }
     }
 }

+ 1 - 4
crates/cashu/src/nuts/nut23.rs

@@ -212,10 +212,7 @@ impl MeltQuoteBolt11Request {
     /// in the request for an amountless bolt11 or in MPP option.
     pub fn amount_msat(&self) -> Result<Amount, Error> {
         let MeltQuoteBolt11Request {
-            request,
-            unit: _,
-            options,
-            ..
+            request, options, ..
         } = self;
 
         match options {

+ 3 - 0
crates/cdk-axum/Cargo.toml

@@ -40,3 +40,6 @@ redis = { version = "0.31.0", features = [
 
 [target.'cfg(target_arch = "wasm32")'.dependencies]
 uuid = { workspace = true, features = ["js"] }
+
+[lints]
+workspace = true

+ 12 - 12
crates/cdk-axum/src/lib.rs

@@ -1,8 +1,6 @@
 //! Axum server for Mint
 
 #![doc = include_str!("../README.md")]
-#![warn(missing_docs)]
-#![warn(rustdoc::bare_urls)]
 
 use std::sync::Arc;
 
@@ -242,16 +240,17 @@ async fn cors_middleware(
     // Handle preflight requests
     if req.method() == axum::http::Method::OPTIONS {
         let mut response = Response::new("".into());
-        response
-            .headers_mut()
-            .insert("Access-Control-Allow-Origin", "*".parse().unwrap());
+        response.headers_mut().insert(
+            "Access-Control-Allow-Origin",
+            "*".parse().expect("Valid header value"),
+        );
         response.headers_mut().insert(
             "Access-Control-Allow-Methods",
-            "GET, POST, OPTIONS".parse().unwrap(),
+            "GET, POST, OPTIONS".parse().expect("Valid header value"),
         );
         response.headers_mut().insert(
             "Access-Control-Allow-Headers",
-            allowed_headers.parse().unwrap(),
+            allowed_headers.parse().expect("Valid header value"),
         );
         return response;
     }
@@ -259,16 +258,17 @@ async fn cors_middleware(
     // Call the next handler
     let mut response = next.run(req).await;
 
-    response
-        .headers_mut()
-        .insert("Access-Control-Allow-Origin", "*".parse().unwrap());
+    response.headers_mut().insert(
+        "Access-Control-Allow-Origin",
+        "*".parse().expect("Valid header value"),
+    );
     response.headers_mut().insert(
         "Access-Control-Allow-Methods",
-        "GET, POST, OPTIONS".parse().unwrap(),
+        "GET, POST, OPTIONS".parse().expect("Valid header value"),
     );
     response.headers_mut().insert(
         "Access-Control-Allow-Headers",
-        allowed_headers.parse().unwrap(),
+        allowed_headers.parse().expect("Valid header value"),
     );
 
     response

+ 3 - 0
crates/cdk-cli/Cargo.toml

@@ -36,3 +36,6 @@ reqwest.workspace = true
 url.workspace = true
 serde_with.workspace = true
 lightning.workspace = true
+
+[lints]
+workspace = true

+ 2 - 1
crates/cdk-cli/src/main.rs

@@ -126,7 +126,8 @@ async fn main() -> Result<()> {
     let work_dir = match &args.work_dir {
         Some(work_dir) => work_dir.clone(),
         None => {
-            let home_dir = home::home_dir().unwrap();
+            let home_dir = home::home_dir()
+                .ok_or_else(|| anyhow::anyhow!("Could not determine home directory"))?;
             home_dir.join(DEFAULT_WORK_DIR)
         }
     };

+ 4 - 1
crates/cdk-cli/src/sub_commands/burn.rs

@@ -18,7 +18,10 @@ pub async fn burn(
 
     match &sub_command_args.mint_url {
         Some(mint_url) => {
-            let wallet = multi_mint_wallet.get_wallet(mint_url).await.unwrap();
+            let wallet = multi_mint_wallet
+                .get_wallet(mint_url)
+                .await
+                .ok_or_else(|| anyhow::anyhow!("Wallet not found for mint: {}", mint_url))?;
             total_burnt = wallet.check_all_pending_proofs().await?;
         }
         None => {

+ 1 - 1
crates/cdk-cli/src/sub_commands/pay_request.rs

@@ -27,7 +27,7 @@ pub async fn pay_request(
 
             let mut user_input = String::new();
             let stdin = io::stdin();
-            io::stdout().flush().unwrap();
+            io::stdout().flush()?;
             stdin.read_line(&mut user_input)?;
 
             let amount: u64 = user_input.trim().parse()?;

+ 13 - 14
crates/cdk-cli/src/sub_commands/send.rs

@@ -133,8 +133,8 @@ pub async fn send(
                     sub_command_args
                         .pubkey
                         .iter()
-                        .map(|p| PublicKey::from_str(p).unwrap())
-                        .collect(),
+                        .map(|p| PublicKey::from_str(p))
+                        .collect::<Result<Vec<_>, _>>()?,
                 ),
             };
 
@@ -144,8 +144,8 @@ pub async fn send(
                     sub_command_args
                         .refund_keys
                         .iter()
-                        .map(|p| PublicKey::from_str(p).unwrap())
-                        .collect(),
+                        .map(|p| PublicKey::from_str(p))
+                        .collect::<Result<Vec<_>, _>>()?,
                 ),
             };
 
@@ -156,8 +156,7 @@ pub async fn send(
                 sub_command_args.required_sigs,
                 None,
                 None,
-            )
-            .unwrap();
+            )?;
 
             Some(SpendingConditions::new_htlc(
                 preimage.clone(),
@@ -171,8 +170,8 @@ pub async fn send(
                     sub_command_args
                         .pubkey
                         .iter()
-                        .map(|p| PublicKey::from_str(p).unwrap())
-                        .collect(),
+                        .map(|p| PublicKey::from_str(p))
+                        .collect::<Result<Vec<_>, _>>()?,
                 ),
             };
 
@@ -182,8 +181,8 @@ pub async fn send(
                     sub_command_args
                         .refund_keys
                         .iter()
-                        .map(|p| PublicKey::from_str(p).unwrap())
-                        .collect(),
+                        .map(|p| PublicKey::from_str(p))
+                        .collect::<Result<Vec<_>, _>>()?,
                 ),
             };
 
@@ -204,14 +203,14 @@ pub async fn send(
                 let pubkeys: Vec<PublicKey> = sub_command_args
                     .pubkey
                     .iter()
-                    .map(|p| PublicKey::from_str(p).unwrap())
-                    .collect();
+                    .map(|p| PublicKey::from_str(p))
+                    .collect::<Result<Vec<_>, _>>()?;
 
                 let refund_keys: Vec<PublicKey> = sub_command_args
                     .refund_keys
                     .iter()
-                    .map(|p| PublicKey::from_str(p).unwrap())
-                    .collect();
+                    .map(|p| PublicKey::from_str(p))
+                    .collect::<Result<Vec<_>, _>>()?;
 
                 let refund_keys = (!refund_keys.is_empty()).then_some(refund_keys);
 

+ 3 - 0
crates/cdk-cln/Cargo.toml

@@ -25,3 +25,6 @@ serde_json.workspace = true
 
 [target.'cfg(target_arch = "wasm32")'.dependencies]
 uuid = { workspace = true, features = ["js"] }
+
+[lints]
+workspace = true

+ 0 - 2
crates/cdk-cln/src/lib.rs

@@ -1,8 +1,6 @@
 //! CDK lightning backend for CLN
 
 #![doc = include_str!("../README.md")]
-#![warn(missing_docs)]
-#![warn(rustdoc::bare_urls)]
 
 use std::cmp::max;
 use std::path::PathBuf;

+ 3 - 0
crates/cdk-common/Cargo.toml

@@ -62,3 +62,6 @@ criterion.workspace = true
 [[bench]]
 name = "transaction_id_benchmark"
 harness = false
+
+[lints]
+workspace = true

+ 1 - 0
crates/cdk-common/src/database/mint/test/mod.rs

@@ -2,6 +2,7 @@
 //!
 //! This set is generic and checks the default and expected behaviour for a mint database
 //! implementation
+#![allow(clippy::unwrap_used)]
 use std::str::FromStr;
 use std::sync::atomic::{AtomicU64, Ordering};
 use std::time::{SystemTime, UNIX_EPOCH};

+ 0 - 2
crates/cdk-common/src/lib.rs

@@ -5,8 +5,6 @@
 //! internal crates.
 
 #![doc = include_str!("../README.md")]
-#![warn(missing_docs)]
-#![warn(rustdoc::bare_urls)]
 
 pub mod task;
 

+ 3 - 0
crates/cdk-fake-wallet/Cargo.toml

@@ -26,3 +26,6 @@ lightning.workspace = true
 tokio-stream.workspace = true
 reqwest.workspace = true
 uuid.workspace = true
+
+[lints]
+workspace = true

+ 6 - 14
crates/cdk-fake-wallet/src/lib.rs

@@ -10,8 +10,6 @@
 //! which is maintained for all invoice types.
 
 #![doc = include_str!("../README.md")]
-#![warn(missing_docs)]
-#![warn(rustdoc::bare_urls)]
 
 use std::cmp::max;
 use std::collections::{HashMap, HashSet, VecDeque};
@@ -280,7 +278,7 @@ impl SecondaryRepaymentQueue {
                     rng.fill(&mut random_bytes);
                     let timestamp = std::time::SystemTime::now()
                         .duration_since(std::time::UNIX_EPOCH)
-                        .unwrap()
+                        .expect("System time before UNIX_EPOCH")
                         .as_nanos() as u64;
 
                     // Create a unique hash combining the original payment identifier, timestamp, and random bytes
@@ -443,13 +441,7 @@ impl MintPayment for FakeWallet {
         &self,
     ) -> Result<Pin<Box<dyn Stream<Item = Event> + Send>>, Self::Err> {
         tracing::info!("Starting stream for fake invoices");
-        let receiver = self
-            .receiver
-            .lock()
-            .await
-            .take()
-            .ok_or(Error::NoReceiver)
-            .unwrap();
+        let receiver = self.receiver.lock().await.take().ok_or(Error::NoReceiver)?;
         let receiver_stream = ReceiverStream::new(receiver);
         Ok(Box::pin(receiver_stream.map(move |wait_response| {
             Event::PaymentReceived(wait_response)
@@ -671,7 +663,7 @@ impl MintPayment for FakeWallet {
                     None => offer_builder,
                 };
 
-                let offer = offer_builder.build().unwrap();
+                let offer = offer_builder.build().expect("Failed to build BOLT12 offer");
 
                 (
                     PaymentIdentifier::OfferId(offer.id().to_string()),
@@ -818,7 +810,7 @@ pub fn create_fake_invoice(amount_msat: u64, description: String) -> Bolt11Invoi
             0x3b, 0x2d, 0xb7, 0x34,
         ][..],
     )
-    .unwrap();
+    .expect("Valid 32-byte secret key");
 
     use bitcoin::secp256k1::rand::rngs::OsRng;
     use bitcoin::secp256k1::rand::Rng;
@@ -826,7 +818,7 @@ pub fn create_fake_invoice(amount_msat: u64, description: String) -> Bolt11Invoi
     let mut random_bytes = [0u8; 32];
     rng.fill(&mut random_bytes);
 
-    let payment_hash = sha256::Hash::from_slice(&random_bytes).unwrap();
+    let payment_hash = sha256::Hash::from_slice(&random_bytes).expect("Valid 32-byte hash input");
     let payment_secret = PaymentSecret([42u8; 32]);
 
     InvoiceBuilder::new(Currency::Bitcoin)
@@ -837,5 +829,5 @@ pub fn create_fake_invoice(amount_msat: u64, description: String) -> Bolt11Invoi
         .current_timestamp()
         .min_final_cltv_expiry_delta(144)
         .build_signed(|hash| Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key))
-        .unwrap()
+        .expect("Failed to build fake invoice")
 }

+ 3 - 0
crates/cdk-ffi/Cargo.toml

@@ -42,3 +42,6 @@ postgres = ["cdk-postgres"]
 [[bin]]
 name = "uniffi-bindgen"
 path = "src/bin/uniffi-bindgen.rs"
+
+[lints]
+workspace = true

+ 2 - 1
crates/cdk-ffi/src/multi_mint_wallet.rs

@@ -188,7 +188,8 @@ impl MultiMintWallet {
             // This is a best-effort operation
             cdk::mint_url::MintUrl::from_str(&url_str).unwrap_or_else(|_| {
                 // Last resort: create a dummy URL that won't match anything
-                cdk::mint_url::MintUrl::from_str("https://invalid.mint").unwrap()
+                cdk::mint_url::MintUrl::from_str("https://invalid.mint")
+                    .expect("Valid hardcoded URL")
             })
         });
         self.inner.remove_mint(&cdk_mint_url).await;

+ 2 - 2
crates/cdk-ffi/src/types/keys.rs

@@ -32,7 +32,7 @@ impl From<KeySetInfo> for cdk::nuts::KeySetInfo {
     fn from(keyset: KeySetInfo) -> Self {
         use std::str::FromStr;
         Self {
-            id: cdk::nuts::Id::from_str(&keyset.id).unwrap(),
+            id: cdk::nuts::Id::from_str(&keyset.id).expect("Invalid keyset ID"),
             unit: keyset.unit.into(),
             active: keyset.active,
             final_expiry: None,
@@ -253,6 +253,6 @@ impl From<cdk::nuts::Id> for Id {
 impl From<Id> for cdk::nuts::Id {
     fn from(id: Id) -> Self {
         use std::str::FromStr;
-        Self::from_str(&id.hex).unwrap()
+        Self::from_str(&id.hex).expect("Invalid ID hex")
     }
 }

+ 10 - 0
crates/cdk-integration-tests/Cargo.toml

@@ -67,3 +67,13 @@ cdk-axum = { workspace = true }
 cdk-fake-wallet = { workspace = true }
 cdk-ffi = { workspace = true }
 tower-http = { workspace = true, features = ["cors"] }
+
+[lints.rust]
+unsafe_code = "forbid"
+
+[lints.clippy]
+unwrap_used = "allow"
+
+[lints.rustdoc]
+missing_docs = "warn"
+bare_urls = "warn"

+ 3 - 0
crates/cdk-ldk-node/Cargo.toml

@@ -29,3 +29,6 @@ tower-http.workspace = true
 rust-embed = "8.5.0"
 serde_urlencoded = "0.7"
 urlencoding = "2.1"
+
+[lints]
+workspace = true

+ 0 - 2
crates/cdk-ldk-node/src/lib.rs

@@ -1,8 +1,6 @@
 //! CDK lightning backend for ldk-node
 
 #![doc = include_str!("../README.md")]
-#![warn(missing_docs)]
-#![warn(rustdoc::bare_urls)]
 
 use std::net::SocketAddr;
 use std::pin::Pin;

+ 22 - 22
crates/cdk-ldk-node/src/web/handlers/channels.rs

@@ -37,11 +37,11 @@ pub struct CloseChannelForm {
 
 pub async fn channels_page(State(_state): State<AppState>) -> Result<Response, StatusCode> {
     // Redirect to the balance page since channels are now part of the Lightning section
-    Ok(Response::builder()
+    Response::builder()
         .status(StatusCode::FOUND)
         .header("Location", "/balance")
         .body(Body::empty())
-        .unwrap())
+        .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)
 }
 
 pub async fn open_channel_page(State(state): State<AppState>) -> Result<Html<String>, StatusCode> {
@@ -106,13 +106,13 @@ pub async fn post_open_channel(
                     a href="/channels/open" { button { "← Try Again" } }
                 }
             };
-            return Ok(Response::builder()
+            return Response::builder()
                 .status(StatusCode::BAD_REQUEST)
                 .header("content-type", "text/html")
                 .body(Body::from(
                     layout_with_status("Open Channel Error", content, true).into_string(),
                 ))
-                .unwrap());
+                .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
         }
     };
 
@@ -126,13 +126,13 @@ pub async fn post_open_channel(
                     a href="/channels/open" { button { "← Try Again" } }
                 }
             };
-            return Ok(Response::builder()
+            return Response::builder()
                 .status(StatusCode::BAD_REQUEST)
                 .header("content-type", "text/html")
                 .body(Body::from(
                     layout_with_status("Open Channel Error", content, true).into_string(),
                 ))
-                .unwrap());
+                .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
         }
     };
 
@@ -150,13 +150,13 @@ pub async fn post_open_channel(
                 a href="/channels/open" { button { "← Try Again" } }
             }
         };
-        return Ok(Response::builder()
+        return Response::builder()
             .status(StatusCode::INTERNAL_SERVER_ERROR)
             .header("content-type", "text/html")
             .body(Body::from(
                 layout_with_status("Open Channel Error", content, true).into_string(),
             ))
-            .unwrap());
+            .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
     }
 
     // Then open the channel
@@ -209,12 +209,12 @@ pub async fn post_open_channel(
         }
     };
 
-    Ok(Response::builder()
+    Response::builder()
         .header("content-type", "text/html")
         .body(Body::from(
             layout_with_status("Open Channel Result", content, true).into_string(),
         ))
-        .unwrap())
+        .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)
 }
 
 pub async fn close_channel_page(
@@ -374,13 +374,13 @@ pub async fn post_close_channel(
                     a href="/channels" { button { "← Back to Channels" } }
                 }
             };
-            return Ok(Response::builder()
+            return Response::builder()
                 .status(StatusCode::BAD_REQUEST)
                 .header("content-type", "text/html")
                 .body(Body::from(
                     layout_with_status("Close Channel Error", content, true).into_string(),
                 ))
-                .unwrap());
+                .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
         }
     };
 
@@ -394,13 +394,13 @@ pub async fn post_close_channel(
                     a href="/channels" { button { "← Back to Channels" } }
                 }
             };
-            return Ok(Response::builder()
+            return Response::builder()
                 .status(StatusCode::BAD_REQUEST)
                 .header("content-type", "text/html")
                 .body(Body::from(
                     layout_with_status("Close Channel Error", content, true).into_string(),
                 ))
-                .unwrap());
+                .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
         }
     };
 
@@ -446,12 +446,12 @@ pub async fn post_close_channel(
         }
     };
 
-    Ok(Response::builder()
+    Response::builder()
         .header("content-type", "text/html")
         .body(Body::from(
             layout_with_status("Close Channel Result", content, true).into_string(),
         ))
-        .unwrap())
+        .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)
 }
 
 pub async fn post_force_close_channel(
@@ -477,13 +477,13 @@ pub async fn post_force_close_channel(
                     a href="/channels" { button { "← Back to Channels" } }
                 }
             };
-            return Ok(Response::builder()
+            return Response::builder()
                 .status(StatusCode::BAD_REQUEST)
                 .header("content-type", "text/html")
                 .body(Body::from(
                     layout_with_status("Force Close Channel Error", content, true).into_string(),
                 ))
-                .unwrap());
+                .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
         }
     };
 
@@ -497,13 +497,13 @@ pub async fn post_force_close_channel(
                     a href="/channels" { button { "← Back to Channels" } }
                 }
             };
-            return Ok(Response::builder()
+            return Response::builder()
                 .status(StatusCode::BAD_REQUEST)
                 .header("content-type", "text/html")
                 .body(Body::from(
                     layout_with_status("Force Close Channel Error", content, true).into_string(),
                 ))
-                .unwrap());
+                .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
         }
     };
 
@@ -551,10 +551,10 @@ pub async fn post_force_close_channel(
         }
     };
 
-    Ok(Response::builder()
+    Response::builder()
         .header("content-type", "text/html")
         .body(Body::from(
             layout_with_status("Force Close Channel Result", content, true).into_string(),
         ))
-        .unwrap())
+        .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)
 }

+ 8 - 7
crates/cdk-ldk-node/src/web/handlers/invoices.rs

@@ -151,7 +151,8 @@ pub async fn post_create_bolt11(
             Ok(desc) => Bolt11InvoiceDescription::Direct(desc),
             Err(_) => {
                 // Fallback to a minimal valid description
-                let desc = Description::new(" ".to_string()).unwrap();
+                let desc =
+                    Description::new(" ".to_string()).expect("single space is valid description");
                 Bolt11InvoiceDescription::Direct(desc)
             }
         }
@@ -169,13 +170,13 @@ pub async fn post_create_bolt11(
                         a href="/invoices" { button { "← Try Again" } }
                     }
                 };
-                return Ok(Response::builder()
+                return Response::builder()
                     .status(StatusCode::BAD_REQUEST)
                     .header("content-type", "text/html")
                     .body(Body::from(
                         layout_with_status(" Error", content, true).into_string(),
                     ))
-                    .unwrap());
+                    .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
             }
         }
     };
@@ -234,12 +235,12 @@ pub async fn post_create_bolt11(
         }
     };
 
-    Ok(Response::builder()
+    Response::builder()
         .header("content-type", "text/html")
         .body(Body::from(
             layout_with_status("BOLT11 Invoice Created", content, true).into_string(),
         ))
-        .unwrap())
+        .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)
 }
 
 pub async fn post_create_bolt12(
@@ -321,10 +322,10 @@ pub async fn post_create_bolt12(
         }
     };
 
-    Ok(Response::builder()
+    Response::builder()
         .header("content-type", "text/html")
         .body(Body::from(
             layout_with_status("BOLT12 Offer Created", content, true).into_string(),
         ))
-        .unwrap())
+        .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)
 }

+ 12 - 12
crates/cdk-ldk-node/src/web/handlers/onchain.rs

@@ -230,11 +230,11 @@ pub async fn post_send_onchain(
     let encoded_form =
         serde_urlencoded::to_string(&form).map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
 
-    Ok(Response::builder()
+    Response::builder()
         .status(StatusCode::FOUND)
         .header("Location", format!("/onchain/confirm?{}", encoded_form))
         .body(Body::empty())
-        .unwrap())
+        .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)
 }
 
 pub async fn onchain_confirm_page(
@@ -258,13 +258,13 @@ pub async fn onchain_confirm_page(
                     a href="/onchain?action=send" { button { "← Back" } }
                 }
             };
-            return Ok(Response::builder()
+            return Response::builder()
                 .status(StatusCode::BAD_REQUEST)
                 .header("content-type", "text/html")
                 .body(Body::from(
                     layout_with_status("Send On-chain Error", content, true).into_string(),
                 ))
-                .unwrap());
+                .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
         }
     };
 
@@ -284,13 +284,13 @@ pub async fn onchain_confirm_page(
                     a href="/onchain?action=send" { button { "← Back" } }
                 }
             };
-            return Ok(Response::builder()
+            return Response::builder()
                 .status(StatusCode::BAD_REQUEST)
                 .header("content-type", "text/html")
                 .body(Body::from(
                     layout_with_status("Send On-chain Error", content, true).into_string(),
                 ))
-                .unwrap());
+                .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
         }
         (amount, false)
     };
@@ -359,12 +359,12 @@ pub async fn onchain_confirm_page(
         }
     };
 
-    Ok(Response::builder()
+    Response::builder()
         .header("content-type", "text/html")
         .body(Body::from(
             layout_with_status("Confirm Transaction", content, true).into_string(),
         ))
-        .unwrap())
+        .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)
 }
 
 async fn execute_onchain_transaction(
@@ -391,13 +391,13 @@ async fn execute_onchain_transaction(
                     a href="/onchain" { button { "← Back" } }
                 }
             };
-            return Ok(Response::builder()
+            return Response::builder()
                 .status(StatusCode::BAD_REQUEST)
                 .header("content-type", "text/html")
                 .body(Body::from(
                     layout_with_status("Send On-chain Error", content, true).into_string(),
                 ))
-                .unwrap());
+                .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
         }
     };
 
@@ -471,10 +471,10 @@ async fn execute_onchain_transaction(
         }
     };
 
-    Ok(Response::builder()
+    Response::builder()
         .header("content-type", "text/html")
         .body(Body::from(
             layout_with_status("Send On-chain Result", content, true).into_string(),
         ))
-        .unwrap())
+        .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)
 }

+ 14 - 14
crates/cdk-ldk-node/src/web/handlers/payments.rs

@@ -371,13 +371,13 @@ pub async fn post_pay_bolt11(
                     a href="/payments" { button { "← Try Again" } }
                 }
             };
-            return Ok(Response::builder()
+            return Response::builder()
                 .status(StatusCode::BAD_REQUEST)
                 .header("content-type", "text/html")
                 .body(Body::from(
                     layout_with_status("Payment Error", content, true).into_string(),
                 ))
-                .unwrap());
+                .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
         }
     };
 
@@ -415,13 +415,13 @@ pub async fn post_pay_bolt11(
                     a href="/payments" { button { "← Try Again" } }
                 }
             };
-            return Ok(Response::builder()
+            return Response::builder()
                 .status(StatusCode::INTERNAL_SERVER_ERROR)
                 .header("content-type", "text/html")
                 .body(Body::from(
                     layout_with_status("Payment Error", content, true).into_string(),
                 ))
-                .unwrap());
+                .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
         }
     };
 
@@ -503,12 +503,12 @@ pub async fn post_pay_bolt11(
         }
     };
 
-    Ok(Response::builder()
+    Response::builder()
         .header("content-type", "text/html")
         .body(Body::from(
             layout_with_status("Payment Result", content, true).into_string(),
         ))
-        .unwrap())
+        .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)
 }
 
 pub async fn post_pay_bolt12(
@@ -525,13 +525,13 @@ pub async fn post_pay_bolt12(
                     a href="/payments" { button { "← Try Again" } }
                 }
             };
-            return Ok(Response::builder()
+            return Response::builder()
                 .status(StatusCode::BAD_REQUEST)
                 .header("content-type", "text/html")
                 .body(Body::from(
                     layout_with_status("Payment Error", content, true).into_string(),
                 ))
-                .unwrap());
+                .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
         }
     };
 
@@ -559,13 +559,13 @@ pub async fn post_pay_bolt12(
                             a href="/payments" { button { "← Try Again" } }
                         }
                     };
-                    return Ok(Response::builder()
+                    return Response::builder()
                         .status(StatusCode::BAD_REQUEST)
                         .header("content-type", "text/html")
                         .body(Body::from(
                             layout_with_status("Payment Error", content, true).into_string(),
                         ))
-                        .unwrap());
+                        .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
                 }
             };
             let amount_msats = amount_btc * 1_000;
@@ -593,13 +593,13 @@ pub async fn post_pay_bolt12(
                     a href="/payments" { button { "← Try Again" } }
                 }
             };
-            return Ok(Response::builder()
+            return Response::builder()
                 .status(StatusCode::INTERNAL_SERVER_ERROR)
                 .header("content-type", "text/html")
                 .body(Body::from(
                     layout_with_status("Payment Error", content, true).into_string(),
                 ))
-                .unwrap());
+                .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
         }
     };
 
@@ -688,10 +688,10 @@ pub async fn post_pay_bolt12(
         }
     };
 
-    Ok(Response::builder()
+    Response::builder()
         .header("content-type", "text/html")
         .body(Body::from(
             layout_with_status("Payment Result", content, true).into_string(),
         ))
-        .unwrap())
+        .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)
 }

+ 7 - 2
crates/cdk-ldk-node/src/web/static_files.rs

@@ -29,12 +29,17 @@ pub async fn static_handler(Path(path): Path<String>) -> impl IntoResponse {
         Some(content) => {
             let content_type = get_content_type(cleaned_path);
             let mut headers = HeaderMap::new();
-            headers.insert(header::CONTENT_TYPE, content_type.parse().unwrap());
+            headers.insert(
+                header::CONTENT_TYPE,
+                content_type.parse().expect("valid content type"),
+            );
 
             // Add cache headers for static assets
             headers.insert(
                 header::CACHE_CONTROL,
-                "public, max-age=31536000".parse().unwrap(),
+                "public, max-age=31536000"
+                    .parse()
+                    .expect("valid cache control"),
             );
 
             (headers, content.data).into_response()

+ 3 - 0
crates/cdk-lnbits/Cargo.toml

@@ -23,3 +23,6 @@ thiserror.workspace = true
 lnbits-rs = "0.9.1"
 serde_json.workspace = true
 rustls.workspace = true
+
+[lints]
+workspace = true

+ 0 - 2
crates/cdk-lnbits/src/lib.rs

@@ -1,8 +1,6 @@
 //! CDK lightning backend for lnbits
 
 #![doc = include_str!("../README.md")]
-#![warn(missing_docs)]
-#![warn(rustdoc::bare_urls)]
 
 use std::cmp::max;
 use std::pin::Pin;

+ 3 - 0
crates/cdk-lnd/Cargo.toml

@@ -31,3 +31,6 @@ rustls-pemfile = "2.2.0"
 
 [build-dependencies]
 tonic-build.workspace = true
+
+[lints]
+workspace = true

+ 2 - 0
crates/cdk-lnd/build.rs

@@ -1,3 +1,5 @@
+#![allow(clippy::unwrap_used)]
+
 fn main() -> Result<(), Box<dyn std::error::Error>> {
     println!("cargo:rerun-if-changed=src/proto/lnrpc.proto");
     println!("cargo:rerun-if-changed=src/proto/routerrpc.proto");

+ 2 - 5
crates/cdk-lnd/src/lib.rs

@@ -3,8 +3,6 @@
 // Copyright (c) 2023 Steffen (MIT)
 
 #![doc = include_str!("../README.md")]
-#![warn(missing_docs)]
-#![warn(rustdoc::bare_urls)]
 
 use std::cmp::max;
 use std::path::PathBuf;
@@ -104,8 +102,7 @@ impl Lnd {
             .map_err(|err| {
                 tracing::error!("Connection error: {}", err.to_string());
                 Error::Connection
-            })
-            .unwrap();
+            })?;
 
         Ok(Self {
             _address: address,
@@ -636,7 +633,7 @@ impl MintPayment for Lnd {
         let mut lnd_client = self.lnd_client.clone();
 
         let invoice_request = lnrpc::PaymentHash {
-            r_hash: hex::decode(payment_identifier.to_string()).unwrap(),
+            r_hash: hex::decode(payment_identifier.to_string())?,
             ..Default::default()
         };
 

+ 3 - 0
crates/cdk-mint-rpc/Cargo.toml

@@ -39,3 +39,6 @@ rustls.workspace = true
 
 [build-dependencies]
 tonic-build.workspace = true
+
+[lints]
+workspace = true

+ 2 - 0
crates/cdk-mint-rpc/build.rs

@@ -1,3 +1,5 @@
+#![allow(clippy::unwrap_used)]
+
 fn main() -> Result<(), Box<dyn std::error::Error>> {
     println!("cargo:rerun-if-changed=src/proto/cdk-mint-rpc.proto");
 

+ 1 - 1
crates/cdk-mint-rpc/src/bin/mint_rpc_cli.rs

@@ -127,7 +127,7 @@ async fn main() -> Result<()> {
         }
 
         // TLS directory exists, configure TLS
-        let server_root_ca_cert = std::fs::read_to_string(work_dir.join("tls/ca.pem")).unwrap();
+        let server_root_ca_cert = std::fs::read_to_string(work_dir.join("tls/ca.pem"))?;
         let server_root_ca_cert = Certificate::from_pem(server_root_ca_cert);
         let client_cert = std::fs::read_to_string(work_dir.join("tls/client.pem"))?;
         let client_key = std::fs::read_to_string(work_dir.join("tls/client.key"))?;

+ 1 - 2
crates/cdk-mint-rpc/src/lib.rs

@@ -1,6 +1,5 @@
 #![doc = include_str!("../README.md")]
-#![warn(missing_docs)]
-#![warn(rustdoc::bare_urls)]
+
 pub mod proto;
 
 pub mod mint_rpc_cli;

+ 3 - 0
crates/cdk-mintd/Cargo.toml

@@ -69,4 +69,7 @@ home.workspace = true
 utoipa = { workspace = true, optional = true }
 utoipa-swagger-ui = { version = "9.0.0", features = ["axum"], optional = true }
 
+[lints]
+workspace = true
+
 [build-dependencies]

+ 2 - 0
crates/cdk-mintd/build.rs

@@ -1,3 +1,5 @@
+#![allow(clippy::unwrap_used)]
+
 fn main() {
     // Check that at least one database feature is enabled
     let has_database = cfg!(feature = "sqlite") || cfg!(feature = "postgres");

+ 8 - 3
crates/cdk-mintd/src/lib.rs

@@ -322,7 +322,9 @@ async fn setup_sqlite_database(
     #[cfg(feature = "sqlcipher")]
     let db = {
         // Get password from command line arguments for sqlcipher
-        MintSqliteDatabase::new((sql_db_path, _password.unwrap())).await?
+        let password = _password
+            .ok_or_else(|| anyhow!("Password required when sqlcipher feature is enabled"))?;
+        MintSqliteDatabase::new((sql_db_path, password)).await?
     };
 
     Ok(Arc::new(db))
@@ -649,7 +651,10 @@ async fn setup_authentication(
                     #[cfg(feature = "sqlcipher")]
                     let sqlite_db = {
                         // Get password from command line arguments for sqlcipher
-                        MintSqliteAuthDatabase::new((sql_db_path, _password.unwrap())).await?
+                        let password = _password.clone().ok_or_else(|| {
+                            anyhow!("Password required when sqlcipher feature is enabled")
+                        })?;
+                        MintSqliteAuthDatabase::new((sql_db_path, password)).await?
                     };
 
                     Arc::new(sqlite_db)
@@ -1027,7 +1032,7 @@ async fn start_services_with_shutdown(
 
     let listener = tokio::net::TcpListener::bind(socket_addr).await?;
 
-    tracing::info!("listening on {}", listener.local_addr().unwrap());
+    tracing::info!("listening on {}", listener.local_addr()?);
 
     // Create a task to wait for the shutdown signal and broadcast it
     let shutdown_broadcast_task = {

+ 0 - 2
crates/cdk-mintd/src/main.rs

@@ -1,6 +1,4 @@
 //! CDK MINTD
-#![warn(missing_docs)]
-#![warn(rustdoc::bare_urls)]
 
 use std::sync::Arc;
 

+ 3 - 0
crates/cdk-payment-processor/Cargo.toml

@@ -70,3 +70,6 @@ bip39.workspace = true
 
 [build-dependencies]
 tonic-build.workspace = true
+
+[lints]
+workspace = true

+ 2 - 0
crates/cdk-payment-processor/build.rs

@@ -1,3 +1,5 @@
+#![allow(clippy::unwrap_used)]
+
 fn main() -> Result<(), Box<dyn std::error::Error>> {
     println!("cargo:rerun-if-changed=src/proto/payment_processor.proto");
     tonic_build::configure()

+ 0 - 2
crates/cdk-payment-processor/src/lib.rs

@@ -1,6 +1,4 @@
 #![doc = include_str!("../README.md")]
-#![warn(missing_docs)]
-#![warn(rustdoc::bare_urls)]
 
 pub mod error;
 /// Protocol types and functionality for the CDK payment processor

+ 3 - 4
crates/cdk-payment-processor/src/proto/server.rs

@@ -247,7 +247,8 @@ impl CdkPaymentProcessor for PaymentProcessorServer {
 
                 cdk_common::payment::OutgoingPaymentOptions::Bolt12(Box::new(
                     cdk_common::payment::Bolt12OutgoingPaymentOptions {
-                        offer: Offer::from_str(&request.request).unwrap(),
+                        offer: Offer::from_str(&request.request)
+                            .expect("Already validated offer above"),
                         max_fee_amount: None,
                         timeout_secs: None,
                         melt_options: request.options.map(Into::into),
@@ -298,9 +299,7 @@ impl CdkPaymentProcessor for PaymentProcessorServer {
                 (CurrencyUnit::Msat, payment_options)
             }
             outgoing_payment_variant::Options::Bolt12(opts) => {
-                let offer = Offer::from_str(&opts.offer)
-                    .map_err(|_| Error::Bolt12Parse)
-                    .unwrap();
+                let offer = Offer::from_str(&opts.offer).map_err(|_| Error::Bolt12Parse)?;
 
                 let payment_options = cdk_common::payment::OutgoingPaymentOptions::Bolt12(
                     Box::new(cdk_common::payment::Bolt12OutgoingPaymentOptions {

+ 3 - 0
crates/cdk-postgres/Cargo.toml

@@ -33,3 +33,6 @@ futures-util = "0.3.31"
 postgres-native-tls = "0.5.1"
 native-tls = "0.2"
 once_cell.workspace = true
+
+[lints]
+workspace = true

+ 3 - 0
crates/cdk-redb/Cargo.toml

@@ -33,3 +33,6 @@ tokio.workspace = true
 
 [target.'cfg(target_arch = "wasm32")'.dependencies]
 uuid = { workspace = true, features = ["js"] }
+
+[lints]
+workspace = true

+ 0 - 2
crates/cdk-redb/src/lib.rs

@@ -1,8 +1,6 @@
 //! SQLite Storage backend for CDK
 
 #![doc = include_str!("../README.md")]
-#![warn(missing_docs)]
-#![warn(rustdoc::bare_urls)]
 
 pub mod error;
 mod migrations;

+ 4 - 5
crates/cdk-redb/src/wallet/mod.rs

@@ -234,11 +234,10 @@ impl WalletDatabase for WalletRedbDatabase {
             .iter()
             .map_err(Error::from)?
             .flatten()
-            .map(|(mint, mint_info)| {
-                (
-                    MintUrl::from_str(mint.value()).unwrap(),
-                    serde_json::from_str(mint_info.value()).ok(),
-                )
+            .filter_map(|(mint, mint_info)| {
+                MintUrl::from_str(mint.value())
+                    .ok()
+                    .map(|url| (url, serde_json::from_str(mint_info.value()).ok()))
             })
             .collect();
 

+ 3 - 0
crates/cdk-signatory/Cargo.toml

@@ -45,3 +45,6 @@ getrandom = { version = "0.2", features = ["js"] }
 
 [build-dependencies]
 tonic-build = { workspace = true, features = ["prost"], optional = true }
+
+[lints]
+workspace = true

+ 3 - 1
crates/cdk-signatory/build.rs

@@ -1,3 +1,5 @@
+#![allow(clippy::unwrap_used)]
+
 fn main() {
     println!("cargo:rerun-if-changed=src/proto/signatory.proto");
 
@@ -7,5 +9,5 @@ fn main() {
         .type_attribute(".", "#[allow(missing_docs)]")
         .field_attribute(".", "#[allow(missing_docs)]")
         .compile_protos(&["src/proto/signatory.proto"], &["src/proto"])
-        .unwrap();
+        .expect("valid proto");
 }

+ 2 - 2
crates/cdk-signatory/src/bin/cli/mod.rs

@@ -8,7 +8,7 @@ use std::str::FromStr;
 use std::sync::Arc;
 use std::{env, fs};
 
-use anyhow::{bail, Result};
+use anyhow::{anyhow, bail, Result};
 use bip39::rand::{thread_rng, Rng};
 use bip39::Mnemonic;
 use cdk_common::database::MintKeysDatabase;
@@ -114,7 +114,7 @@ pub async fn cli_main() -> Result<()> {
     let work_dir = match &args.work_dir {
         Some(work_dir) => work_dir.clone(),
         None => {
-            let home_dir = home::home_dir().unwrap();
+            let home_dir = home::home_dir().ok_or(anyhow!("Unknown how"))?;
             home_dir.join(DEFAULT_WORK_DIR)
         }
     };

+ 2 - 2
crates/cdk-signatory/src/bin/signatory.rs

@@ -7,9 +7,9 @@ fn main() {
     #[cfg(not(target_arch = "wasm32"))]
     {
         use tokio::runtime::Runtime;
-        let rt = Runtime::new().unwrap();
+        let rt = Runtime::new().expect("Runtime created");
         rt.block_on(async {
-            cli::cli_main().await.unwrap();
+            cli::cli_main().await.expect("cli error");
         });
     }
 }

+ 3 - 0
crates/cdk-sql-common/Cargo.toml

@@ -30,3 +30,6 @@ serde_json.workspace = true
 lightning-invoice.workspace = true
 once_cell.workspace = true
 uuid.workspace = true
+
+[lints]
+workspace = true

+ 2 - 0
crates/cdk-sql-common/build.rs

@@ -1,3 +1,5 @@
+#![allow(clippy::unwrap_used)]
+
 use std::cmp::Ordering;
 use std::env;
 use std::fs::{self, File};

+ 0 - 3
crates/cdk-sql-common/src/lib.rs

@@ -1,8 +1,5 @@
 //! SQLite storage backend for cdk
 
-#![warn(missing_docs)]
-#![warn(rustdoc::bare_urls)]
-
 mod common;
 pub mod database;
 mod macros;

+ 3 - 2
crates/cdk-sql-common/src/macros.rs

@@ -5,6 +5,7 @@
 #[macro_export]
 macro_rules! unpack_into {
     (let ($($var:ident),+) = $array:expr) => {
+        #[allow(unused_parens)]
         let ($($var),+) = {
             let mut vec = $array.to_vec();
             vec.reverse();
@@ -12,11 +13,11 @@ macro_rules! unpack_into {
             if vec.len() < required {
                  Err($crate::ConversionError::MissingColumn(required, vec.len()))?;
             }
-            Ok::<_, cdk_common::database::Error>((
+            (
                 $(
                     vec.pop().expect(&format!("Checked length already for {}", stringify!($var)))
                 ),+
-            ))?
+            )
         };
     };
 }

+ 4 - 2
crates/cdk-sql-common/src/mint/mod.rs

@@ -179,7 +179,7 @@ where
             .bind("c", proof.c.to_bytes().to_vec())
             .bind(
                 "witness",
-                proof.witness.map(|w| serde_json::to_string(&w).unwrap()),
+                proof.witness.and_then(|w| serde_json::to_string(&w).inspect_err(|e| tracing::error!("Failed to serialize witness: {:?}", e)).ok()),
             )
             .bind("state", "UNSPENT".to_string())
             .bind("quote_id", quote_id.clone().map(|q| q.to_string()))
@@ -2455,6 +2455,7 @@ fn sql_row_to_mint_quote(
     ))
 }
 
+// FIXME: Replace unwrap with proper error handling
 fn sql_row_to_melt_quote(row: Vec<Column>) -> Result<mint::MeltQuote, Error> {
     unpack_into!(
         let (
@@ -2519,7 +2520,8 @@ fn sql_row_to_melt_quote(row: Vec<Column>) -> Result<mint::MeltQuote, Error> {
                 "Melt quote from pre migrations defaulting to bolt11 {}.",
                 err
             );
-            let bolt11 = Bolt11Invoice::from_str(&request).unwrap();
+            let bolt11 = Bolt11Invoice::from_str(&request)
+                .map_err(|e| Error::Internal(format!("Could not parse invoice: {e}")))?;
             MeltPaymentRequest::Bolt11 { bolt11 }
         }
     };

+ 36 - 7
crates/cdk-sql-common/src/stmt.rs

@@ -82,16 +82,28 @@ pub fn split_sql_parts(input: &str) -> Result<Vec<SqlPart>, SqlParseError> {
             '\'' | '"' => {
                 // Start of string literal
                 let quote = c;
-                current.push(chars.next().unwrap());
+                current.push(
+                    chars
+                        .next()
+                        .ok_or(SqlParseError::UnterminatedStringLiteral)?,
+                );
 
                 let mut closed = false;
                 while let Some(&next) = chars.peek() {
-                    current.push(chars.next().unwrap());
+                    current.push(
+                        chars
+                            .next()
+                            .ok_or(SqlParseError::UnterminatedStringLiteral)?,
+                    );
 
                     if next == quote {
                         if chars.peek() == Some(&quote) {
                             // Escaped quote (e.g. '' inside strings)
-                            current.push(chars.next().unwrap());
+                            current.push(
+                                chars
+                                    .next()
+                                    .ok_or(SqlParseError::UnterminatedStringLiteral)?,
+                            );
                         } else {
                             closed = true;
                             break;
@@ -105,10 +117,19 @@ pub fn split_sql_parts(input: &str) -> Result<Vec<SqlPart>, SqlParseError> {
             }
 
             '-' => {
-                current.push(chars.next().unwrap());
+                current.push(
+                    chars
+                        .next()
+                        .ok_or(SqlParseError::UnterminatedStringLiteral)?,
+                );
+
                 if chars.peek() == Some(&'-') {
                     while let Some(&next) = chars.peek() {
-                        current.push(chars.next().unwrap());
+                        current.push(
+                            chars
+                                .next()
+                                .ok_or(SqlParseError::UnterminatedStringLiteral)?,
+                        );
                         if next == '\n' {
                             break;
                         }
@@ -128,7 +149,11 @@ pub fn split_sql_parts(input: &str) -> Result<Vec<SqlPart>, SqlParseError> {
 
                 while let Some(&next) = chars.peek() {
                     if next.is_alphanumeric() || next == '_' {
-                        name.push(chars.next().unwrap());
+                        name.push(
+                            chars
+                                .next()
+                                .ok_or(SqlParseError::UnterminatedStringLiteral)?,
+                        );
                     } else {
                         break;
                     }
@@ -142,7 +167,11 @@ pub fn split_sql_parts(input: &str) -> Result<Vec<SqlPart>, SqlParseError> {
             }
 
             _ => {
-                current.push(chars.next().unwrap());
+                current.push(
+                    chars
+                        .next()
+                        .ok_or(SqlParseError::UnterminatedStringLiteral)?,
+                );
             }
         }
     }

+ 7 - 5
crates/cdk-sql-common/src/wallet/mod.rs

@@ -515,7 +515,7 @@ where
                 proof
                     .proof
                     .witness
-                    .map(|w| serde_json::to_string(&w).unwrap()),
+                    .and_then(|w| serde_json::to_string(&w).ok()),
             )
             .bind(
                 "dleq_e",
@@ -827,8 +827,9 @@ where
         .fetch_all(conn)
         .await?;
 
-        for id in keys_without_u32 {
-            let id = column_as_string!(id.first().unwrap());
+        for row in keys_without_u32 {
+            unpack_into!(let (id) = row);
+            let id = column_as_string!(id);
 
             if let Ok(id) = Id::from_str(&id) {
                 query(
@@ -858,8 +859,9 @@ where
         .fetch_all(conn)
         .await?;
 
-        for id in keysets_without_u32 {
-            let id = column_as_string!(id.first().unwrap());
+        for row in keysets_without_u32 {
+            unpack_into!(let (id) = row);
+            let id = column_as_string!(id);
 
             if let Ok(id) = Id::from_str(&id) {
                 query(

+ 3 - 0
crates/cdk-sqlite/Cargo.toml

@@ -35,3 +35,6 @@ uuid.workspace = true
 
 [target.'cfg(target_arch = "wasm32")'.dependencies]
 uuid = { workspace = true, features = ["js"] }
+
+[lints]
+workspace = true

+ 0 - 3
crates/cdk-sqlite/src/lib.rs

@@ -1,8 +1,5 @@
 //! SQLite storage backend for cdk
 
-#![warn(missing_docs)]
-#![warn(rustdoc::bare_urls)]
-
 mod async_sqlite;
 mod common;
 

+ 3 - 0
crates/cdk/Cargo.toml

@@ -166,3 +166,6 @@ tokio = { workspace = true, features = ["full"] }
 [[bench]]
 name = "dhke_benchmarks"
 harness = false
+
+[lints]
+workspace = true

+ 0 - 2
crates/cdk/src/lib.rs

@@ -1,7 +1,5 @@
 //! Rust implementation of the Cashu Protocol
 #![doc = include_str!("../README.md")]
-#![warn(missing_docs)]
-#![warn(rustdoc::bare_urls)]
 
 // Disallow enabling `tor` feature on wasm32 with a clear error.
 #[cfg(all(target_arch = "wasm32", feature = "tor"))]

+ 1 - 1
crates/cdk/src/mint/issue/mod.rs

@@ -654,7 +654,7 @@ impl Mint {
             }
         }
 
-        let unit = unit.ok_or(Error::UnsupportedUnit).unwrap();
+        let unit = unit.ok_or(Error::UnsupportedUnit)?;
         ensure_cdk!(unit == mint_quote.unit, Error::UnsupportedUnit);
 
         let operation = Operation::new_mint();

+ 1 - 1
crates/cdk/src/wallet/melt/melt_bolt12.rs

@@ -37,7 +37,7 @@ impl Wallet {
                 .map(|opt| opt.amount_msat())
                 .or_else(|| amount_for_offer(&offer, &CurrencyUnit::Msat).ok())
                 .ok_or(Error::AmountUndefined)?;
-            let amount_quote_unit = to_unit(amount_msat, &CurrencyUnit::Msat, &self.unit).unwrap();
+            let amount_quote_unit = to_unit(amount_msat, &CurrencyUnit::Msat, &self.unit)?;
 
             if quote_res.amount != amount_quote_unit {
                 tracing::warn!(

+ 5 - 1
crates/cdk/src/wallet/mint_connector/http_client.rs

@@ -257,7 +257,11 @@ where
         let transport = self.transport.clone();
         let keys_response = transport.http_get::<KeysResponse>(url, None).await?;
 
-        Ok(keys_response.keysets.first().unwrap().clone())
+        Ok(keys_response
+            .keysets
+            .first()
+            .ok_or(Error::UnknownKeySet)?
+            .clone())
     }
 
     /// Get Keysets [NUT-02]

+ 1 - 2
crates/cdk/src/wallet/swap.rs

@@ -230,8 +230,7 @@ impl Wallet {
             true => {
                 let split_count = amount
                     .unwrap_or(Amount::ZERO)
-                    .split_targeted(&SplitTarget::default(), fee_and_amounts)
-                    .unwrap()
+                    .split_targeted(&SplitTarget::default(), fee_and_amounts)?
                     .len();
 
                 let fee_to_redeem = self