Skip to content

Commit 960164a

Browse files
committed
example using hwi signing with bitbox
1 parent 3e61d2a commit 960164a

File tree

4 files changed

+122
-1
lines changed

4 files changed

+122
-1
lines changed

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ members = [
55
"examples/example_wallet_electrum",
66
"examples/example_wallet_esplora_blocking",
77
"examples/example_wallet_esplora_async",
8-
"examples/example_wallet_rpc",
8+
"examples/example_wallet_rpc",
9+
"examples/example_wallet_hwi_signer",
910
]
1011

1112
[workspace.package]
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[package]
2+
name = "example_wallet_hwi_signer"
3+
version = "0.1.0"
4+
edition = "2021"
5+
authors.workspace = true
6+
7+
[dependencies]
8+
bdk_wallet = { path = "../../wallet", features = ["file_store"] }
9+
bdk_bitcoind_rpc = { version = "0.18" }
10+
tokio = { version = "1", features = ["rt", "rt-multi-thread", "macros"] }
11+
12+
async-hwi = "0.0.27"
13+
anyhow = "1"
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Example signing with HWI Interface
2+
3+
4+
## Requirements
5+
6+
sudo apt install libudev-dev
7+
8+
9+
## Build and run
10+
11+
`$ cargo run `
12+
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
use std::sync::Arc;
2+
3+
use async_hwi::bitbox::api::runtime::TokioRuntime;
4+
use async_hwi::bitbox::api::{usb, BitBox};
5+
use async_hwi::bitbox::NoiseConfigNoCache;
6+
use bdk_wallet::bitcoin::{Network, Psbt};
7+
use bdk_wallet::bitcoin::secp256k1::{Secp256k1, All};
8+
use bdk_wallet::signer::{SignerError, SignerOrdering, TransactionSigner};
9+
use bdk_wallet::KeychainKind;
10+
use bdk_wallet::{signer::SignerCommon, signer::SignerId, Wallet};
11+
12+
use async_hwi::{HWI, bitbox::BitBox02};
13+
use tokio::runtime::Runtime;
14+
15+
#[derive(Debug)]
16+
struct HwiSigner<T: HWI> {
17+
hw_device: T
18+
}
19+
20+
impl<T: HWI> HwiSigner<T> {
21+
22+
async fn sign_tx(&self, psbt: &mut Psbt) -> Result<(), SignerError> {
23+
if let Err(e) = self.hw_device.sign_tx(psbt).await {
24+
return Err(SignerError::External(e.to_string()));
25+
}
26+
Ok(())
27+
}
28+
29+
fn new(hw_device: T) -> Self {
30+
HwiSigner {
31+
hw_device
32+
}
33+
}
34+
35+
fn get_id(&self) -> SignerId {
36+
SignerId::Dummy(0)
37+
}
38+
}
39+
40+
impl<T> SignerCommon for HwiSigner<T>
41+
where T: Sync + Send + HWI {
42+
43+
fn id(&self, _secp: &Secp256k1<All>) -> SignerId {
44+
self.get_id()
45+
}
46+
47+
}
48+
49+
impl<T> TransactionSigner for HwiSigner<T>
50+
where T: Sync + Send + HWI {
51+
52+
fn sign_transaction(
53+
&self,
54+
psbt: &mut Psbt,
55+
_sign_options: &bdk_wallet::SignOptions,
56+
_secp: &Secp256k1<All>,
57+
) -> Result<(), SignerError> {
58+
let rt = Runtime::new().unwrap();
59+
rt.block_on(self.sign_tx(psbt))?;
60+
Ok(())
61+
}
62+
}
63+
64+
#[tokio::main]
65+
async fn main() -> Result<(), anyhow::Error> {
66+
67+
let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/0/*)";
68+
let change_descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/1/*)";
69+
70+
let noise_config = Box::new(NoiseConfigNoCache {});
71+
let bitbox = BitBox::<TokioRuntime>::from_hid_device(
72+
usb::get_any_bitbox02().unwrap(),
73+
noise_config,
74+
).await?;
75+
76+
let pairing_device = bitbox.unlock_and_pair().await?;
77+
let paired_device = pairing_device.wait_confirm().await?;
78+
let bb = BitBox02::from(paired_device);
79+
80+
let _ = bb.register_wallet("test-wallet", descriptor).await.unwrap();
81+
82+
let bitbox_signer = HwiSigner::new(bb);
83+
84+
let mut wallet = Wallet::create(descriptor, change_descriptor)
85+
.network(Network::Testnet)
86+
.create_wallet_no_persist()?;
87+
88+
wallet.add_signer(
89+
KeychainKind::External,
90+
SignerOrdering(100),
91+
Arc::new(bitbox_signer)
92+
);
93+
94+
Ok(())
95+
}

0 commit comments

Comments
 (0)