Skip to content

Commit 4916d40

Browse files
committed
feat(hwi): Update hwi lib to v0.0.30
1 parent 01df5b0 commit 4916d40

File tree

5 files changed

+180
-198
lines changed

5 files changed

+180
-198
lines changed

Cargo.lock

Lines changed: 64 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ tracing = "0.1.41"
2525
tracing-subscriber = "0.3.20"
2626
toml = "0.8.23"
2727
serde= {version = "1.0", features = ["derive"]}
28+
crossbeam ={ version = "0.8.4"}
2829

2930
# Optional dependencies
3031
bdk_bitcoind_rpc = { version = "0.21.0", features = ["std"], optional = true }
@@ -36,7 +37,7 @@ shlex = { version = "1.3.0", optional = true }
3637
payjoin = { version = "1.0.0-rc.1", features = ["v1", "v2", "io", "_test-utils"], optional = true}
3738
reqwest = { version = "0.12.23", default-features = false, optional = true }
3839
url = { version = "2.5.4", optional = true }
39-
async-hwi ={ version = "0.0.29", optional = true }
40+
async-hwi ={ version = "0.0.30", features = ["service", "coldcard", "ledger", "jade", "bitbox"], optional = true }
4041

4142
[features]
4243
default = ["repl", "sqlite"]

src/commands.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -266,10 +266,6 @@ pub struct HwiOpts {
266266
/// External descriptor
267267
#[arg(env = "EXT_DESCRIPTOR", short = 'e', long = "ext_descriptor")]
268268
pub ext_descriptor: Option<String>,
269-
270-
/// Database type
271-
#[arg(short = 'd', long = "database_type")]
272-
pub database_type: Option<DatabaseType>,
273269
}
274270

275271
/// Options to configure a SOCKS5 proxy for a blockchain client connection.

src/handlers.rs

Lines changed: 46 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@ use bdk_redb::Store as RedbStore;
2323
use bdk_wallet::bip39::{Language, Mnemonic};
2424
use bdk_wallet::bitcoin::base64::Engine;
2525
use bdk_wallet::bitcoin::base64::prelude::BASE64_STANDARD;
26-
#[cfg(feature = "hwi")]
27-
use bdk_wallet::bitcoin::hex::DisplayHex;
2826
use bdk_wallet::bitcoin::{
2927
Address, Amount, FeeRate, Network, Psbt, Sequence, Txid,
3028
bip32::{DerivationPath, KeySource},
@@ -1203,135 +1201,68 @@ pub async fn handle_hwi_subcommand(
12031201
hwi_opts: &HwiOpts,
12041202
subcommand: HwiSubCommand,
12051203
) -> Result<serde_json::Value, Error> {
1204+
use async_hwi::AddressScript;
1205+
use bdk_wallet::bitcoin::hex::DisplayHex;
1206+
12061207
match subcommand {
12071208
HwiSubCommand::Devices => {
1208-
let devices = crate::utils::connect_to_hardware_wallet(network, hwi_opts).await?;
1209-
let device = if let Some(device) = devices {
1209+
let device_opt = crate::utils::connect_hwi_device(network, hwi_opts).await?;
1210+
let device = if let Some(device) = device_opt.as_ref() {
12101211
json!({
1211-
"fingerprint": device.get_master_fingerprint().await?.to_string(),
1212+
"fingerprint": device.get_master_fingerprint().await.map_err(Error::HwiError)?.to_string(),
12121213
"model": device.device_kind().to_string(),
12131214
})
12141215
} else {
12151216
json!(null)
12161217
};
1217-
Ok(json!({ "devices": device }))
1218+
Ok(json!({ "device": device }))
12181219
}
12191220
HwiSubCommand::Register => {
1220-
let policy = hwi_opts.ext_descriptor.clone().ok_or_else(|| {
1221-
Error::Generic("External descriptor required for wallet registration".to_string())
1222-
})?;
1223-
let wallet_name = hwi_opts.wallet.clone().ok_or_else(|| {
1224-
Error::Generic("Wallet name is required for wallet registration".to_string())
1225-
})?;
1226-
1227-
let device = crate::utils::connect_to_hardware_wallet(network, hwi_opts).await?;
1228-
1229-
match device {
1230-
None => Ok(json!({
1231-
"success": false,
1232-
"error": "No hardware wallet detected"
1233-
})),
1234-
Some(device) => match device.register_wallet(&wallet_name, &policy).await {
1235-
Ok(hmac_opt) => {
1236-
let hmac_hex = hmac_opt.map(|h| {
1237-
let bytes: &[u8] = &h;
1238-
bytes.to_lower_hex_string()
1239-
});
1240-
Ok(json!({
1241-
"success": true,
1242-
"hmac": hmac_hex
1243-
}))
1244-
}
1245-
Err(e) => Err(Error::Generic(format!("Wallet registration failed: {e}"))),
1246-
},
1247-
}
1221+
let policy = hwi_opts
1222+
.ext_descriptor
1223+
.clone()
1224+
.ok_or_else(|| Error::Generic("External descriptor required".to_string()))?;
1225+
let wallet_name = hwi_opts
1226+
.wallet
1227+
.clone()
1228+
.ok_or_else(|| Error::Generic("Wallet name required".to_string()))?;
1229+
let device_opt = crate::utils::connect_hwi_device(network, hwi_opts).await?;
1230+
let device = device_opt
1231+
.ok_or_else(|| Error::Generic("No hardware wallet detected".to_string()))?;
1232+
tracing::debug!(
1233+
"Registering wallet '{}' with policy '{}'",
1234+
wallet_name,
1235+
policy
1236+
);
1237+
let hmac_opt = device
1238+
.register_wallet(&wallet_name, &policy)
1239+
.await
1240+
.map_err(Error::HwiError)?;
1241+
let hmac_hex = hmac_opt.map(|h| h.to_lower_hex_string());
1242+
Ok(json!({ "success": true, "hmac": hmac_hex }))
12481243
}
12491244
HwiSubCommand::Address => {
1250-
let ext_descriptor = hwi_opts.ext_descriptor.clone().ok_or_else(|| {
1251-
Error::Generic("External descriptor required for address generation".to_string())
1252-
})?;
1253-
let wallet_name = hwi_opts.wallet.clone().ok_or_else(|| {
1254-
Error::Generic("Wallet name is required for address generation".to_string())
1255-
})?;
1256-
1257-
let database = hwi_opts.database_type.clone().ok_or_else(|| {
1258-
Error::Generic("Database type is required for address generation".to_string())
1259-
})?;
1260-
1261-
let home_dir = prepare_home_dir(None)?;
1262-
let database_path = prepare_wallet_db_dir(&home_dir, wallet_name.as_str())?;
1263-
1264-
let wallet_opts = WalletOpts {
1265-
wallet: Some(wallet_name),
1266-
verbose: false,
1267-
ext_descriptor: ext_descriptor,
1268-
int_descriptor: None,
1269-
#[cfg(any(
1270-
feature = "electrum",
1271-
feature = "esplora",
1272-
feature = "rpc",
1273-
feature = "cbf"
1274-
))]
1275-
client_type: {
1276-
if cfg!(feature = "electrum") {
1277-
ClientType::Electrum
1278-
} else if cfg!(feature = "esplora") {
1279-
ClientType::Esplora
1280-
} else if cfg!(feature = "rpc") {
1281-
ClientType::Rpc
1282-
} else {
1283-
ClientType::Cbf
1284-
}
1285-
},
1286-
#[cfg(any(feature = "sqlite", feature = "redb"))]
1287-
database_type: database,
1288-
#[cfg(any(feature = "electrum", feature = "esplora", feature = "rpc"))]
1289-
url: String::new(),
1290-
#[cfg(feature = "electrum")]
1291-
batch_size: 10,
1292-
#[cfg(feature = "esplora")]
1293-
parallel_requests: 5,
1294-
#[cfg(feature = "rpc")]
1295-
basic_auth: (String::new(), String::new()),
1296-
#[cfg(feature = "rpc")]
1297-
cookie: None,
1298-
#[cfg(feature = "cbf")]
1299-
compactfilter_opts: CompactFilterOpts { conn_count: 2 },
1245+
let device_opt = crate::utils::connect_hwi_device(network, hwi_opts).await?;
1246+
let device = device_opt
1247+
.ok_or_else(|| Error::Generic("No hardware wallet detected".to_string()))?;
1248+
let address_script = AddressScript::Miniscript {
1249+
index: 0,
1250+
change: false,
13001251
};
1301-
1302-
#[cfg(feature = "sqlite")]
1303-
let mut wallet = if hwi_opts.database_type.is_some() {
1304-
let db_file = database_path.join("wallet.sqlite");
1305-
let mut persister = Connection::open(db_file)?;
1306-
let mut wallet = new_persisted_wallet(network, &mut persister, &wallet_opts)?;
1307-
wallet.persist(&mut persister)?;
1308-
wallet
1309-
} else {
1310-
return Err(Error::Generic(
1311-
"Could not connect to sqlite database".to_string(),
1312-
));
1313-
};
1314-
1315-
#[cfg(not(feature = "sqlite"))]
1316-
let mut wallet = new_wallet(network, &wallet_opts)?;
1317-
1318-
let address = wallet.next_unused_address(KeychainKind::External);
1319-
Ok(json!({ "address": address.address }))
1252+
device
1253+
.display_address(&address_script)
1254+
.await
1255+
.map_err(Error::HwiError)?;
1256+
Ok(json!({ "success": true, "message": "Address displayed and verified on device" }))
13201257
}
13211258
HwiSubCommand::Sign { psbt } => {
13221259
let mut psbt = Psbt::from_str(&psbt)
13231260
.map_err(|e| Error::Generic(format!("Failed to parse PSBT: {e}")))?;
1324-
let device = crate::utils::connect_to_hardware_wallet(network, hwi_opts).await?;
1325-
let signed_psbt = if let Some(device) = device {
1326-
device
1327-
.sign_tx(&mut psbt)
1328-
.await
1329-
.map_err(|e| Error::Generic(format!("Failed to sign PSBT: {e}")))?;
1330-
Some(psbt.to_string())
1331-
} else {
1332-
None
1333-
};
1334-
Ok(json!({ "psbt": signed_psbt }))
1261+
let device_opt = crate::utils::connect_hwi_device(network, hwi_opts).await?;
1262+
let device = device_opt
1263+
.ok_or_else(|| Error::Generic("No hardware wallet detected".to_string()))?;
1264+
device.sign_tx(&mut psbt).await.map_err(Error::HwiError)?;
1265+
Ok(json!({ "psbt": psbt.to_string() }))
13351266
}
13361267
}
13371268
}
@@ -1570,7 +1501,7 @@ pub(crate) async fn handle_command(cli_opts: CliOpts) -> Result<String, Error> {
15701501
subcommand,
15711502
} => {
15721503
let result = handle_hwi_subcommand(network, &hwi_opts, subcommand).await?;
1573-
Ok(serde_json::to_string_pretty(&result).map_err(|e| Error::SerdeJson(e))?)
1504+
Ok(serde_json::to_string_pretty(&result).map_err(Error::SerdeJson)?)
15741505
}
15751506
};
15761507
result

0 commit comments

Comments
 (0)