Add jade hardware wallet
This commit is contained in:
parent
b7a72e064d
commit
6b0c93c5c3
124
gui/Cargo.lock
generated
124
gui/Cargo.lock
generated
@ -2,27 +2,6 @@
|
|||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "CoreFoundation-sys"
|
|
||||||
version = "0.1.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d0e9889e6db118d49d88d84728d0e964d973a5680befb5f85f55141beea5c20b"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"mach 0.1.2",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "IOKit-sys"
|
|
||||||
version = "0.1.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "99696c398cbaf669d2368076bdb3d627fb0ce51a26899d7c61228c5c0af3bf4a"
|
|
||||||
dependencies = [
|
|
||||||
"CoreFoundation-sys",
|
|
||||||
"libc",
|
|
||||||
"mach 0.1.2",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ab_glyph"
|
name = "ab_glyph"
|
||||||
version = "0.2.20"
|
version = "0.2.20"
|
||||||
@ -214,9 +193,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-hwi"
|
name = "async-hwi"
|
||||||
version = "0.0.16"
|
version = "0.0.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "912663643d018301fb5534949e8430515c7cdc9bf453bfefba2dc70dc854dd31"
|
checksum = "647a2513ce55652719759c6416e98de94b19a349dc94e1be4924b0487f73ce9b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"bitbox-api",
|
"bitbox-api",
|
||||||
@ -227,10 +206,17 @@ dependencies = [
|
|||||||
"ledger-apdu",
|
"ledger-apdu",
|
||||||
"ledger-transport-hidapi",
|
"ledger-transport-hidapi",
|
||||||
"ledger_bitcoin_client",
|
"ledger_bitcoin_client",
|
||||||
|
"prost 0.12.2",
|
||||||
|
"prost-derive 0.12.2",
|
||||||
"regex",
|
"regex",
|
||||||
|
"reqwest",
|
||||||
|
"serde",
|
||||||
|
"serde_bytes",
|
||||||
|
"serde_cbor",
|
||||||
"serialport",
|
"serialport",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-serial",
|
"tokio-serial",
|
||||||
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1353,7 +1339,7 @@ checksum = "bdd2162b720141a91a054640662d3edce3d50a944a50ffca5313cd951abb35b4"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bit_field",
|
"bit_field",
|
||||||
"flume",
|
"flume",
|
||||||
"half",
|
"half 2.2.1",
|
||||||
"lebe",
|
"lebe",
|
||||||
"miniz_oxide",
|
"miniz_oxide",
|
||||||
"rayon-core",
|
"rayon-core",
|
||||||
@ -1853,6 +1839,12 @@ dependencies = [
|
|||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "half"
|
||||||
|
version = "1.8.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "half"
|
name = "half"
|
||||||
version = "2.2.1"
|
version = "2.2.1"
|
||||||
@ -2132,7 +2124,7 @@ dependencies = [
|
|||||||
"bitflags 2.4.2",
|
"bitflags 2.4.2",
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
"cosmic-text",
|
"cosmic-text",
|
||||||
"half",
|
"half 2.2.1",
|
||||||
"iced_core",
|
"iced_core",
|
||||||
"iced_futures",
|
"iced_futures",
|
||||||
"image",
|
"image",
|
||||||
@ -2337,6 +2329,16 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "io-kit-sys"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "617ee6cf8e3f66f3b4ea67a4058564628cde41901316e19f559e14c7c72c5e7b"
|
||||||
|
dependencies = [
|
||||||
|
"core-foundation-sys",
|
||||||
|
"mach2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "io-lifetimes"
|
name = "io-lifetimes"
|
||||||
version = "1.0.11"
|
version = "1.0.11"
|
||||||
@ -2810,19 +2812,10 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mach"
|
name = "mach2"
|
||||||
version = "0.1.2"
|
version = "0.4.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2fd13ee2dd61cc82833ba05ade5a30bb3d63f7ced605ef827063c63078302de9"
|
checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709"
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "mach"
|
|
||||||
version = "0.3.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
@ -2957,7 +2950,7 @@ checksum = "20a4c60ca5c9c0e114b3bd66ff4aa5f9b2b175442be51ca6c4365d687a97a2ac"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"mio",
|
"mio",
|
||||||
"nix 0.26.2",
|
"nix",
|
||||||
"serialport",
|
"serialport",
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
@ -3033,17 +3026,6 @@ dependencies = [
|
|||||||
"jni-sys",
|
"jni-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "nix"
|
|
||||||
version = "0.24.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags 1.3.2",
|
|
||||||
"cfg-if",
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nix"
|
name = "nix"
|
||||||
version = "0.26.2"
|
version = "0.26.2"
|
||||||
@ -4253,6 +4235,25 @@ dependencies = [
|
|||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_bytes"
|
||||||
|
version = "0.11.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8b8497c313fd43ab992087548117643f6fcd935cbf36f176ffda0aacf9591734"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_cbor"
|
||||||
|
version = "0.11.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5"
|
||||||
|
dependencies = [
|
||||||
|
"half 1.8.3",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.186"
|
version = "1.0.186"
|
||||||
@ -4289,18 +4290,20 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serialport"
|
name = "serialport"
|
||||||
version = "4.2.0"
|
version = "4.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "aab92efb5cf60ad310548bc3f16fa6b0d950019cb7ed8ff41968c3d03721cf12"
|
checksum = "8f5a15d0be940df84846264b09b51b10b931fb2f275becb80934e3568a016828"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"CoreFoundation-sys",
|
"bitflags 2.4.2",
|
||||||
"IOKit-sys",
|
|
||||||
"bitflags 1.3.2",
|
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
|
"core-foundation-sys",
|
||||||
|
"io-kit-sys",
|
||||||
"libudev",
|
"libudev",
|
||||||
"mach 0.3.2",
|
"mach2",
|
||||||
"nix 0.24.3",
|
"nix",
|
||||||
"regex",
|
"regex",
|
||||||
|
"scopeguard",
|
||||||
|
"unescaper",
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -4942,6 +4945,15 @@ version = "1.16.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
|
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unescaper"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0adf6ad32eb5b3cadff915f7b770faaac8f7ff0476633aa29eb0d9584d889d34"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-bidi"
|
name = "unicode-bidi"
|
||||||
version = "0.3.13"
|
version = "0.3.13"
|
||||||
|
|||||||
@ -15,7 +15,7 @@ path = "src/main.rs"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
async-trait = "0.1"
|
async-trait = "0.1"
|
||||||
async-hwi = "0.0.16"
|
async-hwi = "0.0.17"
|
||||||
liana = { git = "https://github.com/wizardsardine/liana", branch = "master", default-features = false, features = ["nonblocking_shutdown"] }
|
liana = { git = "https://github.com/wizardsardine/liana", branch = "master", default-features = false, features = ["nonblocking_shutdown"] }
|
||||||
liana_ui = { path = "ui" }
|
liana_ui = { path = "ui" }
|
||||||
backtrace = "0.3"
|
backtrace = "0.3"
|
||||||
|
|||||||
@ -53,6 +53,9 @@ pub fn hw_list_view(
|
|||||||
UnsupportedReason::NotPartOfWallet(fg) => {
|
UnsupportedReason::NotPartOfWallet(fg) => {
|
||||||
hw::unrelated_hardware_wallet(&kind.to_string(), version.as_ref(), fg)
|
hw::unrelated_hardware_wallet(&kind.to_string(), version.as_ref(), fg)
|
||||||
}
|
}
|
||||||
|
UnsupportedReason::WrongNetwork => {
|
||||||
|
hw::wrong_network_hardware_wallet(&kind.to_string(), version.as_ref())
|
||||||
|
}
|
||||||
_ => hw::unsupported_hardware_wallet(&kind.to_string(), version.as_ref()),
|
_ => hw::unsupported_hardware_wallet(&kind.to_string(), version.as_ref()),
|
||||||
},
|
},
|
||||||
HardwareWallet::Locked {
|
HardwareWallet::Locked {
|
||||||
@ -111,6 +114,9 @@ pub fn hw_list_view_for_registration(
|
|||||||
UnsupportedReason::NotPartOfWallet(fg) => {
|
UnsupportedReason::NotPartOfWallet(fg) => {
|
||||||
hw::unrelated_hardware_wallet(&kind.to_string(), version.as_ref(), fg)
|
hw::unrelated_hardware_wallet(&kind.to_string(), version.as_ref(), fg)
|
||||||
}
|
}
|
||||||
|
UnsupportedReason::WrongNetwork => {
|
||||||
|
hw::wrong_network_hardware_wallet(&kind.to_string(), version.as_ref())
|
||||||
|
}
|
||||||
_ => hw::unsupported_hardware_wallet(&kind.to_string(), version.as_ref()),
|
_ => hw::unsupported_hardware_wallet(&kind.to_string(), version.as_ref()),
|
||||||
},
|
},
|
||||||
HardwareWallet::Locked {
|
HardwareWallet::Locked {
|
||||||
@ -180,6 +186,9 @@ pub fn hw_list_view_verify_address(
|
|||||||
UnsupportedReason::NotPartOfWallet(fg) => {
|
UnsupportedReason::NotPartOfWallet(fg) => {
|
||||||
hw::unrelated_hardware_wallet(&kind.to_string(), version.as_ref(), fg)
|
hw::unrelated_hardware_wallet(&kind.to_string(), version.as_ref(), fg)
|
||||||
}
|
}
|
||||||
|
UnsupportedReason::WrongNetwork => {
|
||||||
|
hw::wrong_network_hardware_wallet(&kind.to_string(), version.as_ref())
|
||||||
|
}
|
||||||
_ => hw::unsupported_hardware_wallet(&kind.to_string(), version.as_ref()),
|
_ => hw::unsupported_hardware_wallet(&kind.to_string(), version.as_ref()),
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
|
|||||||
245
gui/src/hw.rs
245
gui/src/hw.rs
@ -8,7 +8,9 @@ use std::{
|
|||||||
use crate::app::{settings, wallet::Wallet};
|
use crate::app::{settings, wallet::Wallet};
|
||||||
use async_hwi::{
|
use async_hwi::{
|
||||||
bitbox::{api::runtime, BitBox02, PairingBitbox02},
|
bitbox::{api::runtime, BitBox02, PairingBitbox02},
|
||||||
coldcard, ledger, specter, DeviceKind, Error as HWIError, Version, HWI,
|
coldcard,
|
||||||
|
jade::{self, Jade},
|
||||||
|
ledger, specter, DeviceKind, Error as HWIError, Version, HWI,
|
||||||
};
|
};
|
||||||
use liana::miniscript::bitcoin::{bip32::Fingerprint, hashes::hex::FromHex, Network};
|
use liana::miniscript::bitcoin::{bip32::Fingerprint, hashes::hex::FromHex, Network};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -21,6 +23,7 @@ pub enum UnsupportedReason {
|
|||||||
},
|
},
|
||||||
Method(&'static str),
|
Method(&'static str),
|
||||||
NotPartOfWallet(Fingerprint),
|
NotPartOfWallet(Fingerprint),
|
||||||
|
WrongNetwork,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Todo drop the Clone, to remove the Mutex on HardwareWallet::Locked
|
// Todo drop the Clone, to remove the Mutex on HardwareWallet::Locked
|
||||||
@ -51,7 +54,8 @@ pub enum HardwareWallet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub enum LockedDevice {
|
pub enum LockedDevice {
|
||||||
BitBox02(PairingBitbox02<runtime::TokioRuntime>),
|
BitBox02(Box<PairingBitbox02<runtime::TokioRuntime>>),
|
||||||
|
Jade(Jade<jade::SerialTransport>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Debug for LockedDevice {
|
impl std::fmt::Debug for LockedDevice {
|
||||||
@ -221,25 +225,47 @@ impl HardwareWallets {
|
|||||||
*alias = self.aliases.get(fingerprint).cloned();
|
*alias = self.aliases.get(fingerprint).cloned();
|
||||||
}
|
}
|
||||||
HardwareWallet::Locked { device, id, .. } => {
|
HardwareWallet::Locked { device, id, .. } => {
|
||||||
if let Some(LockedDevice::BitBox02(bb)) = device.lock().unwrap().take()
|
match device.lock().unwrap().take() {
|
||||||
{
|
None => {}
|
||||||
let id = id.to_string();
|
Some(LockedDevice::BitBox02(bb)) => {
|
||||||
let id_cloned = id.clone();
|
let id = id.to_string();
|
||||||
let network = self.network;
|
let id_cloned = id.clone();
|
||||||
let wallet = self.wallet.clone();
|
let network = self.network;
|
||||||
cmds.push(Command::perform(
|
let wallet = self.wallet.clone();
|
||||||
async move {
|
cmds.push(Command::perform(
|
||||||
let paired_bb = bb.wait_confirm().await?;
|
async move {
|
||||||
let mut bitbox2 =
|
let paired_bb = bb.wait_confirm().await?;
|
||||||
BitBox02::from(paired_bb).with_network(network);
|
let mut bitbox2 =
|
||||||
let fingerprint = bitbox2.get_master_fingerprint().await?;
|
BitBox02::from(paired_bb).with_network(network);
|
||||||
let mut registered = false;
|
let fingerprint =
|
||||||
if let Some(wallet) = &wallet {
|
bitbox2.get_master_fingerprint().await?;
|
||||||
let desc = wallet.main_descriptor.to_string();
|
let mut registered = false;
|
||||||
bitbox2 = bitbox2.with_policy(&desc)?;
|
if let Some(wallet) = &wallet {
|
||||||
registered =
|
let desc = wallet.main_descriptor.to_string();
|
||||||
bitbox2.is_policy_registered(&desc).await?;
|
bitbox2 = bitbox2.with_policy(&desc)?;
|
||||||
if wallet.descriptor_keys().contains(&fingerprint) {
|
registered =
|
||||||
|
bitbox2.is_policy_registered(&desc).await?;
|
||||||
|
if wallet.descriptor_keys().contains(&fingerprint) {
|
||||||
|
Ok(HardwareWallet::Supported {
|
||||||
|
id: id.clone(),
|
||||||
|
kind: DeviceKind::BitBox02,
|
||||||
|
fingerprint,
|
||||||
|
device: bitbox2.into(),
|
||||||
|
version: None,
|
||||||
|
registered: Some(registered),
|
||||||
|
alias: None,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Ok(HardwareWallet::Unsupported {
|
||||||
|
id: id.clone(),
|
||||||
|
kind: DeviceKind::BitBox02,
|
||||||
|
version: None,
|
||||||
|
reason: UnsupportedReason::NotPartOfWallet(
|
||||||
|
fingerprint,
|
||||||
|
),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
Ok(HardwareWallet::Supported {
|
Ok(HardwareWallet::Supported {
|
||||||
id: id.clone(),
|
id: id.clone(),
|
||||||
kind: DeviceKind::BitBox02,
|
kind: DeviceKind::BitBox02,
|
||||||
@ -249,30 +275,31 @@ impl HardwareWallets {
|
|||||||
registered: Some(registered),
|
registered: Some(registered),
|
||||||
alias: None,
|
alias: None,
|
||||||
})
|
})
|
||||||
} else {
|
|
||||||
Ok(HardwareWallet::Unsupported {
|
|
||||||
id: id.clone(),
|
|
||||||
kind: DeviceKind::BitBox02,
|
|
||||||
version: None,
|
|
||||||
reason: UnsupportedReason::NotPartOfWallet(
|
|
||||||
fingerprint,
|
|
||||||
),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
} else {
|
},
|
||||||
Ok(HardwareWallet::Supported {
|
|res| HardwareWalletMessage::Unlocked(id_cloned, res),
|
||||||
id: id.clone(),
|
));
|
||||||
kind: DeviceKind::BitBox02,
|
}
|
||||||
fingerprint,
|
Some(LockedDevice::Jade(device)) => {
|
||||||
device: bitbox2.into(),
|
let id = id.clone();
|
||||||
version: None,
|
let id_cloned = id.clone();
|
||||||
registered: Some(registered),
|
let network = self.network;
|
||||||
alias: None,
|
let wallet = self.wallet.clone();
|
||||||
})
|
cmds.push(Command::perform(
|
||||||
}
|
async move {
|
||||||
},
|
device.auth().await?;
|
||||||
|res| HardwareWalletMessage::Unlocked(id_cloned, res),
|
handle_jade_device(
|
||||||
));
|
id,
|
||||||
|
network,
|
||||||
|
device,
|
||||||
|
wallet.as_ref().map(|w| w.as_ref()),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
},
|
||||||
|
|res| HardwareWalletMessage::Unlocked(id_cloned, res),
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
@ -286,8 +313,8 @@ impl HardwareWallets {
|
|||||||
}
|
}
|
||||||
HardwareWalletMessage::Unlocked(id, res) => {
|
HardwareWalletMessage::Unlocked(id, res) => {
|
||||||
match res {
|
match res {
|
||||||
Err(_) => {
|
Err(e) => {
|
||||||
warn!("Pairing failed with an external device");
|
warn!("Pairing failed with an external device {}", e);
|
||||||
self.list.retain(|hw| hw.id() != &id);
|
self.list.retain(|hw| hw.id() != &id);
|
||||||
}
|
}
|
||||||
Ok(hw) => {
|
Ok(hw) => {
|
||||||
@ -317,6 +344,7 @@ impl HardwareWallets {
|
|||||||
iced::subscription::unfold(
|
iced::subscription::unfold(
|
||||||
format!("refresh-{}", self.network),
|
format!("refresh-{}", self.network),
|
||||||
State {
|
State {
|
||||||
|
network: self.network,
|
||||||
keys_aliases: self.aliases.clone(),
|
keys_aliases: self.aliases.clone(),
|
||||||
wallet: self.wallet.clone(),
|
wallet: self.wallet.clone(),
|
||||||
connected_supported_hws: Vec::new(),
|
connected_supported_hws: Vec::new(),
|
||||||
@ -329,6 +357,7 @@ impl HardwareWallets {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct State {
|
struct State {
|
||||||
|
network: Network,
|
||||||
keys_aliases: HashMap<Fingerprint, String>,
|
keys_aliases: HashMap<Fingerprint, String>,
|
||||||
wallet: Option<Arc<Wallet>>,
|
wallet: Option<Arc<Wallet>>,
|
||||||
connected_supported_hws: Vec<String>,
|
connected_supported_hws: Vec<String>,
|
||||||
@ -406,6 +435,38 @@ async fn refresh(mut state: State) -> (HardwareWalletMessage, State) {
|
|||||||
}
|
}
|
||||||
Err(e) => warn!("Error while listing specter wallets: {}", e),
|
Err(e) => warn!("Error while listing specter wallets: {}", e),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
match jade::SerialTransport::enumerate_potential_ports() {
|
||||||
|
Ok(ports) => {
|
||||||
|
for port in ports {
|
||||||
|
let id = format!("jade-{}", port);
|
||||||
|
if state.connected_supported_hws.contains(&id) {
|
||||||
|
still.push(id);
|
||||||
|
} else {
|
||||||
|
let device =
|
||||||
|
Jade::new(jade::SerialTransport::new(port)).with_network(state.network);
|
||||||
|
match handle_jade_device(
|
||||||
|
id,
|
||||||
|
state.network,
|
||||||
|
device,
|
||||||
|
state.wallet.as_ref().map(|w| w.as_ref()),
|
||||||
|
Some(&state.keys_aliases),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(hw) => {
|
||||||
|
hws.push(hw);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
warn!("{:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => warn!("Error while listing jade devices: {}", e),
|
||||||
|
}
|
||||||
|
|
||||||
match ledger::LedgerSimulator::try_connect().await {
|
match ledger::LedgerSimulator::try_connect().await {
|
||||||
Ok(mut device) => {
|
Ok(mut device) => {
|
||||||
let id = "ledger-simulator".to_string();
|
let id = "ledger-simulator".to_string();
|
||||||
@ -497,7 +558,9 @@ async fn refresh(mut state: State) -> (HardwareWalletMessage, State) {
|
|||||||
id,
|
id,
|
||||||
kind: DeviceKind::BitBox02,
|
kind: DeviceKind::BitBox02,
|
||||||
pairing_code: device.pairing_code().map(|s| s.replace('\n', " ")),
|
pairing_code: device.pairing_code().map(|s| s.replace('\n', " ")),
|
||||||
device: Arc::new(Mutex::new(Some(LockedDevice::BitBox02(device)))),
|
device: Arc::new(Mutex::new(Some(LockedDevice::BitBox02(Box::new(
|
||||||
|
device,
|
||||||
|
))))),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -648,6 +711,94 @@ async fn refresh(mut state: State) -> (HardwareWalletMessage, State) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn handle_jade_device(
|
||||||
|
id: String,
|
||||||
|
network: Network,
|
||||||
|
device: Jade<async_hwi::jade::SerialTransport>,
|
||||||
|
wallet: Option<&Wallet>,
|
||||||
|
keys_aliases: Option<&HashMap<Fingerprint, String>>,
|
||||||
|
) -> Result<HardwareWallet, HWIError> {
|
||||||
|
let info = device.get_info().await?;
|
||||||
|
let version = async_hwi::parse_version(&info.jade_version).ok();
|
||||||
|
// Jade may not be setup for the current network
|
||||||
|
if (network == Network::Bitcoin
|
||||||
|
&& info.jade_networks != jade::api::JadeNetworks::Main
|
||||||
|
&& info.jade_networks != jade::api::JadeNetworks::All)
|
||||||
|
|| (network != Network::Bitcoin && info.jade_networks == jade::api::JadeNetworks::Main)
|
||||||
|
{
|
||||||
|
Ok(HardwareWallet::Unsupported {
|
||||||
|
id,
|
||||||
|
kind: device.device_kind(),
|
||||||
|
version,
|
||||||
|
reason: UnsupportedReason::WrongNetwork,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
match info.jade_state {
|
||||||
|
jade::api::JadeState::Locked
|
||||||
|
| jade::api::JadeState::Temp
|
||||||
|
| jade::api::JadeState::Uninit
|
||||||
|
| jade::api::JadeState::Unsaved => Ok(HardwareWallet::Locked {
|
||||||
|
id,
|
||||||
|
kind: DeviceKind::Jade,
|
||||||
|
pairing_code: None,
|
||||||
|
device: Arc::new(Mutex::new(Some(LockedDevice::Jade(device)))),
|
||||||
|
}),
|
||||||
|
jade::api::JadeState::Ready => {
|
||||||
|
let kind = device.device_kind();
|
||||||
|
let version = device.get_version().await.ok();
|
||||||
|
let fingerprint = match device.get_master_fingerprint().await {
|
||||||
|
Err(HWIError::NetworkMismatch) => {
|
||||||
|
return Ok(HardwareWallet::Unsupported {
|
||||||
|
id: id.clone(),
|
||||||
|
kind,
|
||||||
|
version,
|
||||||
|
reason: UnsupportedReason::WrongNetwork,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
Ok(fingerprint) => fingerprint,
|
||||||
|
};
|
||||||
|
let alias = keys_aliases.and_then(|aliases| aliases.get(&fingerprint).cloned());
|
||||||
|
if let Some(wallet) = &wallet {
|
||||||
|
if wallet.descriptor_keys().contains(&fingerprint) {
|
||||||
|
let desc = wallet.main_descriptor.to_string();
|
||||||
|
let device = device.with_wallet(wallet.name.clone());
|
||||||
|
let registered = device.is_wallet_registered(&wallet.name, &desc).await?;
|
||||||
|
Ok(HardwareWallet::Supported {
|
||||||
|
id: id.clone(),
|
||||||
|
kind,
|
||||||
|
fingerprint,
|
||||||
|
device: Arc::new(device),
|
||||||
|
version,
|
||||||
|
registered: Some(registered),
|
||||||
|
alias,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Ok(HardwareWallet::Unsupported {
|
||||||
|
id: id.clone(),
|
||||||
|
kind,
|
||||||
|
version,
|
||||||
|
reason: UnsupportedReason::NotPartOfWallet(fingerprint),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ok(HardwareWallet::Supported {
|
||||||
|
id: id.clone(),
|
||||||
|
kind,
|
||||||
|
fingerprint,
|
||||||
|
device: Arc::new(device),
|
||||||
|
version,
|
||||||
|
registered: Some(false),
|
||||||
|
alias,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct AsRefWrap<'a, T> {
|
struct AsRefWrap<'a, T> {
|
||||||
inner: &'a T,
|
inner: &'a T,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,7 +23,7 @@ use liana_ui::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
bitcoind::{ConfigField, RpcAuthType, RpcAuthValues, StartInternalBitcoindError},
|
bitcoind::{ConfigField, RpcAuthType, RpcAuthValues, StartInternalBitcoindError},
|
||||||
hw::{is_compatible_with_tapminiscript, HardwareWallet},
|
hw::{is_compatible_with_tapminiscript, HardwareWallet, UnsupportedReason},
|
||||||
installer::{
|
installer::{
|
||||||
message::{self, Message},
|
message::{self, Message},
|
||||||
prompt,
|
prompt,
|
||||||
@ -614,9 +614,20 @@ pub fn hardware_wallet_xpubs<'a>(
|
|||||||
hw::supported_hardware_wallet(kind, version.as_ref(), fingerprint, alias.as_ref())
|
hw::supported_hardware_wallet(kind, version.as_ref(), fingerprint, alias.as_ref())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HardwareWallet::Unsupported { version, kind, .. } => {
|
HardwareWallet::Unsupported {
|
||||||
hw::unsupported_hardware_wallet(&kind.to_string(), version.as_ref())
|
version,
|
||||||
}
|
kind,
|
||||||
|
reason,
|
||||||
|
..
|
||||||
|
} => match reason {
|
||||||
|
UnsupportedReason::NotPartOfWallet(fg) => {
|
||||||
|
hw::unrelated_hardware_wallet(&kind.to_string(), version.as_ref(), fg)
|
||||||
|
}
|
||||||
|
UnsupportedReason::WrongNetwork => {
|
||||||
|
hw::wrong_network_hardware_wallet(&kind.to_string(), version.as_ref())
|
||||||
|
}
|
||||||
|
_ => hw::unsupported_hardware_wallet(&kind.to_string(), version.as_ref()),
|
||||||
|
},
|
||||||
HardwareWallet::Locked {
|
HardwareWallet::Locked {
|
||||||
kind, pairing_code, ..
|
kind, pairing_code, ..
|
||||||
} => hw::locked_hardware_wallet(kind, pairing_code.as_ref()),
|
} => hw::locked_hardware_wallet(kind, pairing_code.as_ref()),
|
||||||
@ -1745,9 +1756,20 @@ pub fn hw_list_view(
|
|||||||
hw::supported_hardware_wallet(kind, version.as_ref(), fingerprint, alias.as_ref())
|
hw::supported_hardware_wallet(kind, version.as_ref(), fingerprint, alias.as_ref())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HardwareWallet::Unsupported { version, kind, .. } => {
|
HardwareWallet::Unsupported {
|
||||||
hw::unsupported_hardware_wallet(&kind.to_string(), version.as_ref())
|
version,
|
||||||
}
|
kind,
|
||||||
|
reason,
|
||||||
|
..
|
||||||
|
} => match reason {
|
||||||
|
UnsupportedReason::NotPartOfWallet(fg) => {
|
||||||
|
hw::unrelated_hardware_wallet(&kind.to_string(), version.as_ref(), fg)
|
||||||
|
}
|
||||||
|
UnsupportedReason::WrongNetwork => {
|
||||||
|
hw::wrong_network_hardware_wallet(&kind.to_string(), version.as_ref())
|
||||||
|
}
|
||||||
|
_ => hw::unsupported_hardware_wallet(&kind.to_string(), version.as_ref()),
|
||||||
|
},
|
||||||
HardwareWallet::Locked {
|
HardwareWallet::Locked {
|
||||||
kind, pairing_code, ..
|
kind, pairing_code, ..
|
||||||
} => hw::locked_hardware_wallet(kind, pairing_code.as_ref()),
|
} => hw::locked_hardware_wallet(kind, pairing_code.as_ref()),
|
||||||
|
|||||||
@ -14,7 +14,14 @@ pub fn locked_hardware_wallet<'a, T: 'a, K: Display>(
|
|||||||
column(vec![
|
column(vec![
|
||||||
Row::new()
|
Row::new()
|
||||||
.spacing(5)
|
.spacing(5)
|
||||||
.push(text::p1_bold("Locked, check code:"))
|
.push(text::p1_bold(format!(
|
||||||
|
"Locked{}",
|
||||||
|
if pairing_code.is_some() {
|
||||||
|
", check code:"
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
}
|
||||||
|
)))
|
||||||
.push_maybe(pairing_code.map(|a| text::p1_bold(a)))
|
.push_maybe(pairing_code.map(|a| text::p1_bold(a)))
|
||||||
.into(),
|
.into(),
|
||||||
Row::new()
|
Row::new()
|
||||||
@ -277,6 +284,38 @@ pub fn registration_success_hardware_wallet<'a, T: 'a, K: Display, V: Display, F
|
|||||||
.padding(10)
|
.padding(10)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn wrong_network_hardware_wallet<'a, T: 'a, K: Display, V: Display>(
|
||||||
|
kind: K,
|
||||||
|
version: Option<V>,
|
||||||
|
) -> Container<'a, T> {
|
||||||
|
container(
|
||||||
|
row(vec![
|
||||||
|
column(vec![
|
||||||
|
Row::new()
|
||||||
|
.spacing(5)
|
||||||
|
.push(text::p1_bold("Wrong network in the device settings"))
|
||||||
|
.into(),
|
||||||
|
Row::new()
|
||||||
|
.spacing(5)
|
||||||
|
.push(text::caption(kind.to_string()))
|
||||||
|
.push_maybe(version.map(|v| text::caption(v.to_string())))
|
||||||
|
.into(),
|
||||||
|
])
|
||||||
|
.width(Length::Fill)
|
||||||
|
.into(),
|
||||||
|
tooltip::Tooltip::new(
|
||||||
|
icon::warning_icon(),
|
||||||
|
"The wrong bitcoin application is open or the device was initialized with the wrong network",
|
||||||
|
tooltip::Position::Bottom,
|
||||||
|
)
|
||||||
|
.style(theme::Container::Card(theme::Card::Simple))
|
||||||
|
.into(),
|
||||||
|
])
|
||||||
|
.align_items(Alignment::Center),
|
||||||
|
)
|
||||||
|
.padding(10)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn unsupported_hardware_wallet<'a, T: 'a, K: Display, V: Display>(
|
pub fn unsupported_hardware_wallet<'a, T: 'a, K: Display, V: Display>(
|
||||||
kind: K,
|
kind: K,
|
||||||
version: Option<V>,
|
version: Option<V>,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user