From 15e4ef413cf596cdc3923e358d28ce3b03bef731 Mon Sep 17 00:00:00 2001 From: pythcoiner Date: Wed, 11 Mar 2026 04:16:33 +0100 Subject: [PATCH 1/2] lib: clippyfy --- .github/workflows/main.yml | 2 +- cli/src/bin/hwi.rs | 6 +++--- cli/src/lib.rs | 4 ++-- src/bitbox.rs | 6 +++--- src/coldcard.rs | 6 +++--- src/jade/mod.rs | 20 ++++++++++---------- src/jade/pinserver.rs | 2 +- src/ledger.rs | 2 +- src/lib.rs | 8 ++++---- src/service.rs | 2 +- src/specter.rs | 9 ++++----- src/utils.rs | 2 +- 12 files changed, 34 insertions(+), 35 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f54d798..c6eb314 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -9,7 +9,7 @@ jobs: - uses: actions/checkout@v1 - uses: actions-rs/toolchain@v1 with: - toolchain: 1.81.0 + toolchain: 1.88.0 components: rustfmt, clippy override: true - name: rustfmt diff --git a/cli/src/bin/hwi.rs b/cli/src/bin/hwi.rs index 14c98ec..8f121bb 100644 --- a/cli/src/bin/hwi.rs +++ b/cli/src/bin/hwi.rs @@ -151,7 +151,7 @@ async fn main() -> Result<(), Box> { eprint!("{}", device.get_master_fingerprint().await?); eprint!(" {}", device.device_kind()); if let Ok(version) = device.get_version().await.map(|v| v.to_string()) { - eprint!(" {}", version); + eprint!(" {version}"); } eprintln!(); } @@ -194,7 +194,7 @@ async fn main() -> Result<(), Box> { _ => ("".into(), policy.clone()), }; let res = device.is_wallet_registered(&name, &policy).await?; - eprintln!("{}", res); + eprintln!("{res}"); } } Commands::Psbt(PsbtCommands::Sign { @@ -219,7 +219,7 @@ async fn main() -> Result<(), Box> { } } device.sign_tx(&mut psbt).await?; - eprintln!("{}", psbt); + eprintln!("{psbt}"); } } } diff --git a/cli/src/lib.rs b/cli/src/lib.rs index 2b3b9ed..1d064f0 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -33,14 +33,14 @@ pub mod command { } match Jade::enumerate().await { - Err(e) => println!("{:?}", e), + Err(e) => println!("{e:?}"), Ok(devices) => { for device in devices { let device = device.with_network(network); if let Ok(info) = device.get_info().await { if info.jade_state == jade::api::JadeState::Locked { if let Err(e) = device.auth().await { - eprintln!("auth {:?}", e); + eprintln!("auth {e:?}"); continue; } } diff --git a/src/bitbox.rs b/src/bitbox.rs index 9210520..4e14463 100644 --- a/src/bitbox.rs +++ b/src/bitbox.rs @@ -407,7 +407,7 @@ pub fn extract_script_config_policy(policy: &str) -> Result { let mut pubkeys: Vec = Vec::new(); for (i, key_str) in pubkeys_str.iter().enumerate() { - descriptor_template = descriptor_template.replace(key_str, &format!("@{}", i)); + descriptor_template = descriptor_template.replace(key_str, &format!("@{i}")); let pubkey = if let Ok(key) = Xpub::from_str(key_str) { KeyInfo { path: None, @@ -428,7 +428,7 @@ pub fn extract_script_config_policy(policy: &str) -> Result { let derivation_path = if path_str.is_empty() { DerivationPath::master() } else { - DerivationPath::from_str(&format!("m/{}", path_str)) + DerivationPath::from_str(&format!("m/{path_str}")) .map_err(|e| HWIError::InvalidParameter("policy", e.to_string()))? }; @@ -462,7 +462,7 @@ pub fn extract_first_appended_derivation_with_some_wildcard( ) -> Result<(Vec, bip389::Wildcard), HWIError> { let re = Regex::new(r"@\d+/[^,)]+").unwrap(); for capture in re.find_iter(template) { - if capture.as_str().contains(&format!("@{}", key_index)) { + if capture.as_str().contains(&format!("@{key_index}")) { if let Some((_, appended)) = capture.as_str().split_once('/') { let (derivations, wildcard) = bip389::parse_xkey_deriv(appended)?; if wildcard != bip389::Wildcard::None { diff --git a/src/coldcard.rs b/src/coldcard.rs index c259b3c..b38e99b 100644 --- a/src/coldcard.rs +++ b/src/coldcard.rs @@ -69,10 +69,10 @@ impl HWI for Coldcard { let path = if path.starts_with("m/") { path } else { - format!("m/{}", path) + format!("m/{path}") }; let path = coldcard::protocol::DerivationPath::new(&path) - .map_err(|e| HWIError::InvalidParameter("path", format!("{:?}", e)))?; + .map_err(|e| HWIError::InvalidParameter("path", format!("{e:?}")))?; let s = self.device()?.xpub(Some(path))?; Xpub::from_str(&s).map_err(|e| HWIError::Device(e.to_string())) } @@ -98,7 +98,7 @@ impl HWI for Coldcard { name: &str, policy: &str, ) -> Result, HWIError> { - let payload = format!("{{\"name\":\"{}\",\"desc\":\"{}\"}}", name, policy); + let payload = format!("{{\"name\":\"{name}\",\"desc\":\"{policy}\"}}"); let _ = self.device()?.miniscript_enroll(payload.as_bytes())?; Ok(None) } diff --git a/src/jade/mod.rs b/src/jade/mod.rs index 70ce247..5fff569 100644 --- a/src/jade/mod.rs +++ b/src/jade/mod.rs @@ -219,7 +219,7 @@ impl HWI for Jade { datavalues: keys .into_iter() .enumerate() - .map(|(i, key)| (format!("@{}", i), key)) + .map(|(i, key)| (format!("@{i}"), key)) .collect(), }), ) @@ -244,7 +244,7 @@ impl HWI for Jade { let datavalues: BTreeMap = keys .into_iter() .enumerate() - .map(|(i, key)| (format!("@{}", i), key)) + .map(|(i, key)| (format!("@{i}"), key)) .collect(); Ok(registered.descriptor_name == name @@ -501,11 +501,11 @@ impl From for TransportError { impl std::fmt::Display for TransportError { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { - Self::Serialize(e) => write!(f, "{}", e), + Self::Serialize(e) => write!(f, "{e}"), Self::NoErrorOrResult => write!(f, "No Error or Result"), Self::NonceMismatch => write!(f, "Nonce mismatched"), - Self::Io(e) => write!(f, "{}", e), - Self::Serial(e) => write!(f, "{}", e), + Self::Io(e) => write!(f, "{e}"), + Self::Serial(e) => write!(f, "{e}"), } } } @@ -533,9 +533,9 @@ impl From for JadeError { impl std::fmt::Display for JadeError { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { - Self::Transport(e) => write!(f, "{}", e), - Self::Rpc(e) => write!(f, "{:?}", e), - Self::PinServer(e) => write!(f, "{:?}", e), + Self::Transport(e) => write!(f, "{e}"), + Self::Rpc(e) => write!(f, "{e:?}"), + Self::PinServer(e) => write!(f, "{e:?}"), Self::HandShakeRefused => write!(f, "Handshake with pinserver refused"), } } @@ -551,10 +551,10 @@ impl From for HWIError { } else if e.code == api::ErrorCode::NetworkMismatch as i32 { HWIError::NetworkMismatch } else { - HWIError::Device(format!("{:?}", e)) + HWIError::Device(format!("{e:?}")) } } - JadeError::PinServer(e) => HWIError::Device(format!("{:?}", e)), + JadeError::PinServer(e) => HWIError::Device(format!("{e:?}")), JadeError::HandShakeRefused => { HWIError::Device("Handshake with pinserver refused".to_string()) } diff --git a/src/jade/pinserver.rs b/src/jade/pinserver.rs index cc7325e..a9a371f 100644 --- a/src/jade/pinserver.rs +++ b/src/jade/pinserver.rs @@ -31,7 +31,7 @@ impl PinServerClient { if res.status().is_success() { res.json().await.map_err(Error::from) } else { - Err(Error::Server(format!("{:?}", res))) + Err(Error::Server(format!("{res:?}"))) } } } diff --git a/src/ledger.rs b/src/ledger.rs index 31a30dd..5922e61 100644 --- a/src/ledger.rs +++ b/src/ledger.rs @@ -320,7 +320,7 @@ impl From> for HWIError { return HWIError::UserRefused; } }; - HWIError::Device(format!("{:#?}", e)) + HWIError::Device(format!("{e:#?}")) } } diff --git a/src/lib.rs b/src/lib.rs index 02b1b46..5a30420 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -45,7 +45,7 @@ pub enum Error { impl std::fmt::Display for Error { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { - Error::ParsingPolicy(e) => write!(f, "{}", e), + Error::ParsingPolicy(e) => write!(f, "{e}"), Error::MissingPolicy => write!(f, "Missing policy"), Error::UnsupportedVersion => write!(f, "Unsupported version"), Error::UnsupportedInput => write!(f, "Unsupported input"), @@ -53,9 +53,9 @@ impl std::fmt::Display for Error { Error::DeviceDisconnected => write!(f, "Device disconnected"), Error::DeviceNotFound => write!(f, "Device not found"), Error::DeviceDidNotSign => write!(f, "Device did not sign"), - Error::Device(e) => write!(f, "{}", e), - Error::InvalidParameter(param, e) => write!(f, "Invalid parameter {}: {}", param, e), - Error::Unexpected(e) => write!(f, "{}", e), + Error::Device(e) => write!(f, "{e}"), + Error::InvalidParameter(param, e) => write!(f, "Invalid parameter {param}: {e}"), + Error::Unexpected(e) => write!(f, "{e}"), Error::UserRefused => write!(f, "User refused operation"), Error::NetworkMismatch => write!(f, "Device network is different"), Error::Bip86ChangeIndex => { diff --git a/src/service.rs b/src/service.rs index d7d7fb4..48ef235 100644 --- a/src/service.rs +++ b/src/service.rs @@ -1442,7 +1442,7 @@ fn handle_bitbox02( /// Prefer serial number for stable ID across USB ports; fall back to path. fn bitbox_id(device_info: &ledger::DeviceInfo) -> String { let id = if let Some(sn) = device_info.serial_number() { - format!("bitbox-{}", sn) + format!("bitbox-{sn}") } else { format!( "bitbox-{:?}-{}-{}", diff --git a/src/specter.rs b/src/specter.rs index 6da6729..db29fce 100644 --- a/src/specter.rs +++ b/src/specter.rs @@ -38,7 +38,7 @@ impl Specter { pub async fn get_extended_pubkey(&self, path: &DerivationPath) -> Result { self.transport - .request(&format!("\r\n\r\nxpub {}\r\n", path)) + .request(&format!("\r\n\r\nxpub {path}\r\n")) .await .and_then(|resp| Xpub::from_str(&resp).map_err(|e| SpecterError::Device(e.to_string()))) } @@ -74,7 +74,7 @@ impl Specter { pub async fn sign(&self, psbt: &Psbt) -> Result { self.transport - .request(&format!("\r\n\r\nsign {}\r\n", psbt)) + .request(&format!("\r\n\r\nsign {psbt}\r\n")) .await .and_then(|resp| { if resp == "error: User cancelled" { @@ -300,8 +300,7 @@ impl SerialTransport { }) .collect()), Err(e) => Err(SpecterError::Device(format!( - "Error listing serial ports: {}", - e + "Error listing serial ports: {e}" ))), } } @@ -332,7 +331,7 @@ impl std::fmt::Display for SpecterError { match self { Self::DeviceNotFound => write!(f, "Specter not found"), Self::DeviceDidNotSign => write!(f, "Specter did not sign the psbt"), - Self::Device(e) => write!(f, "Specter error: {}", e), + Self::Device(e) => write!(f, "Specter error: {e}"), Self::UserCancelled => write!(f, "User cancelled operation"), } } diff --git a/src/utils.rs b/src/utils.rs index 00d3194..908cfab 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -143,7 +143,7 @@ pub fn extract_keys_and_template(policy: &str) -> Result<(String, Ve let mut pubkeys: Vec = Vec::new(); for (i, key_str) in pubkeys_str.iter().enumerate() { - descriptor_template = descriptor_template.replace(key_str, &format!("@{}", i)); + descriptor_template = descriptor_template.replace(key_str, &format!("@{i}")); let pubkey = T::from_str(key_str).map_err(|_| Error::UnsupportedInput)?; pubkeys.push(pubkey); } From cc2f1cd1822c2b0ab94536bc015bc693ae6afc8c Mon Sep 17 00:00:00 2001 From: pythcoiner Date: Wed, 29 Oct 2025 02:47:20 +0100 Subject: [PATCH 2/2] lib: bump coldcard dep & uses Coldcard::sign_psbt_miniscript() --- .github/workflows/main.yml | 2 +- Cargo.lock | 4 ++-- Cargo.toml | 2 +- README.md | 2 +- src/coldcard.rs | 12 +++++++++++- 5 files changed, 16 insertions(+), 6 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c6eb314..9108810 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -25,7 +25,7 @@ jobs: strategy: matrix: toolchain: - - 1.81.0 + - 1.85.0 - nightly os: - ubuntu-latest diff --git a/Cargo.lock b/Cargo.lock index 5e3de6a..93e162a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -478,9 +478,9 @@ checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "coldcard" -version = "0.12.2" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aaaf3f7409edc40001c30a4c1337f21558a8ceba2a4afe807da841a38ce83d6" +checksum = "1178252cca421753b1024d240d43e502b019f51ca8022652587cdad4347d58b7" dependencies = [ "aes", "base58", diff --git a/Cargo.toml b/Cargo.toml index fd7cee8..cc276f9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,7 +47,7 @@ reqwest = { version = "0.11", default-features = false, features = ["json", "rus bitbox-api = { version = "0.9.0", default-features = false, features = ["usb", "tokio", "multithreaded", "simulator"], optional = true } # coldcard -coldcard = { version = "0.12.2", optional = true } +coldcard = { version = "0.13.0", optional = true } # ledger ledger_bitcoin_client = { version = "0.5.0", optional = true } diff --git a/README.md b/README.md index c823330..890258a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # async-hwi -Current **Minimum Supported Rust Version**: v1.81 +Current **Minimum Supported Rust Version**: v1.81 (1.85 if coldcard feature enabled) ```rust /// HWI is the common Hardware Wallet Interface. diff --git a/src/coldcard.rs b/src/coldcard.rs index b38e99b..6e48227 100644 --- a/src/coldcard.rs +++ b/src/coldcard.rs @@ -8,6 +8,7 @@ use bitcoin::{ bip32::{DerivationPath, Fingerprint, Xpub}, psbt::Psbt, }; +use coldcard::protocol::DescriptorName; use hidapi::DeviceInfo; use crate::{parse_version, AddressScript, DeviceKind, Error as HWIError, Version, HWI}; @@ -121,7 +122,16 @@ impl HWI for Coldcard { async fn sign_tx(&self, psbt: &mut Psbt) -> Result<(), HWIError> { let mut cc = self.device()?; - let _ = cc.sign_psbt(&psbt.serialize(), api::SignMode::Signed)?; + let wallet_name = if let Some(name) = self.wallet_name.clone() { + Some( + DescriptorName::new(name) + .map_err(|_| HWIError::Unexpected("Coldcard: Invalid wallet name"))?, + ) + } else { + None + }; + + let _ = cc.sign_psbt_miniscript(&psbt.serialize(), api::SignMode::Signed, wallet_name)?; let tx = loop { if let Some(tx) = cc.get_signed_tx()? {