Skip to content

Commit 983c057

Browse files
Merge #30: Update README.md, add CONTRIBUTING.md, update docs
5a5cdca Small docs updates (Daniela Brozzoni) 4202320 Derive useful methods (Daniela Brozzoni) 4b0ade7 Add CONTRIBUTING.md (Daniela Brozzoni) f68bae6 Update README.md (Daniela Brozzoni) Pull request description: Based on #31 Closes #28 ACKs for top commit: danielabrozzoni: self-ACK 5a5cdca Tree-SHA512: db2500aa7520fe1772352e8d1053e34ba06dd11a5a83e6cbf5372f74bcd982e9908447a3e50f9afec76d5a360edca8de250b488b97b479ca94243cec3409c65b
2 parents 52e09a3 + 5a5cdca commit 983c057

File tree

5 files changed

+206
-106
lines changed

5 files changed

+206
-106
lines changed

CONTRIBUTING.md

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
Contributing to rust-hwi
2+
===========================================
3+
The rust-hwi project operates an open contributor model where anyone is welcome to
4+
contribute towards development in the form of peer review, documentation,
5+
testing and patches.
6+
7+
Anyone is invited to contribute without regard to technical experience,
8+
"expertise", OSS experience, age, or other concern. However, the development of
9+
cryptocurrencies demands a high-level of rigor, adversarial thinking, thorough
10+
testing and risk-minimization.
11+
Any bug may cost users real money. That being said, we deeply welcome people
12+
contributing for the first time to an open source project or picking up Rust while
13+
contributing. Don't be shy, you'll learn.
14+
15+
Communications Channels
16+
-----------------------
17+
18+
Communication about rust-hwi happens primarily on the [BDK Discord](https://discord.gg/dstn4dQ), in the #rust-hwi channel.
19+
20+
Discussion about code base improvements happens in GitHub [issues](https://github.com/bitcoindevkit/rust-hwi/issues) and
21+
on [pull requests](https://github.com/bitcoindevkit/rust-hwi/pulls).
22+
23+
Contribution Workflow
24+
---------------------
25+
26+
The codebase is maintained using the "contributor workflow" where everyone
27+
without exception contributes patch proposals using "pull requests". This
28+
facilitates social contribution, easy testing and peer review.
29+
30+
To contribute a patch, the worflow is a as follows:
31+
32+
1. Fork Repository
33+
2. Create topic branch
34+
3. Commit patches
35+
36+
In general commits should be atomic and diffs should be easy to read.
37+
For this reason do not mix any formatting fixes or code moves with actual code
38+
changes. Further, each commit, individually, should compile and pass tests, in
39+
order to ensure git bisect and other automated tools function properly.
40+
41+
When adding a new feature, thought must be given to the long term technical
42+
debt.
43+
Every new feature should be covered by unit tests where possible.
44+
45+
When refactoring, structure your PR to make it easy to review and don't
46+
hesitate to split it into multiple small, focused PRs.
47+
48+
The Minimal Supported Rust Version is 1.41.1 (enforced by our CI).
49+
50+
Commits should cover both the issue fixed and the solution's rationale.
51+
These [guidelines](https://chris.beams.io/posts/git-commit/) should be kept in mind.
52+
53+
To facilitate communication with other contributors, the project is making use
54+
of GitHub's "assignee" field. First check that no one is assigned and then
55+
comment suggesting that you're working on it. If someone is already assigned,
56+
don't hesitate to ask if the assigned party or previous commenters are still
57+
working on it if it has been awhile.
58+
59+
Deprecation policy
60+
------------------
61+
62+
Where possible, breaking existing APIs should be avoided. Instead, add new APIs and
63+
use [`#[deprecated]`](https://github.com/rust-lang/rfcs/blob/master/text/1270-deprecation.md)
64+
to discourage use of the old one.
65+
66+
Deprecated APIs are typically maintained for one release cycle. In other words, an
67+
API that has been deprecated with the 0.10 release can be expected to be removed in the
68+
0.11 release. This allows for smoother upgrades without incurring too much technical
69+
debt inside this library.
70+
71+
If you deprecated an API as part of a contribution, we encourage you to "own" that API
72+
and send a follow-up to remove it as part of the next release cycle.
73+
74+
Peer review
75+
-----------
76+
77+
Anyone may participate in peer review which is expressed by comments in the
78+
pull request. Typically reviewers will review the code for obvious errors, as
79+
well as test out the patch set and opine on the technical merits of the patch.
80+
PR should be reviewed first on the conceptual level before focusing on code
81+
style or grammar fixes.
82+
83+
Coding Conventions
84+
------------------
85+
86+
This codebase uses spaces, not tabs.
87+
Use `cargo fmt` with the default settings to format code before committing.
88+
This is also enforced by the CI.
89+
90+
Going further
91+
-------------
92+
93+
You may be interested by Jon Atacks guide on [How to review Bitcoin Core PRs](https://github.com/jonatack/bitcoin-development/blob/master/how-to-review-bitcoin-core-prs.md)
94+
and [How to make Bitcoin Core PRs](https://github.com/jonatack/bitcoin-development/blob/master/how-to-make-bitcoin-core-prs.md).
95+
While there are differences between the projects in terms of context and
96+
maturity, many of the suggestions offered apply to this project.
97+
98+
Overall, have fun :)

README.md

Lines changed: 44 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# rust-hwi
2-
Rust wrapper for [HWI](https://github.com/bitcoin-core/HWI/).
2+
Rust wrapper for the [Bitcoin Hardware Wallet Interface](https://github.com/bitcoin-core/HWI/) library.
3+
4+
<a href="https://crates.io/crates/hwi"><img alt="Crate Info" src="https://img.shields.io/crates/v/hwi.svg"/></a>
5+
<a href="https://docs.rs/hwi"><img alt="API Docs" src="https://img.shields.io/badge/docs.rs-hwi-green"/></a>
6+
<a href="https://blog.rust-lang.org/2020/02/27/Rust-1.41.1.html"><img alt="Rustc Version 1.41+" src="https://img.shields.io/badge/rustc-1.41%2B-lightgrey.svg"/></a>
7+
<a href="https://discord.gg/d7NkDKm"><img alt="Chat on Discord" src="https://img.shields.io/discord/753336465005608961?logo=discord"></a>
8+
9+
This library internally uses PyO3 to call HWI's functions. It is not a re-implementation of HWI in native Rust.
310

411
## Prerequisites
512

@@ -24,7 +31,7 @@ brew install libusb
2431

2532
- Clone the repo
2633
```
27-
git clone https://github.com/MagicalBitcoin/rust-hwi.git && cd rust-hwi
34+
git clone https://github.com/bitcoindevkit/rust-hwi.git && cd rust-hwi
2835
```
2936

3037
- Create a virtualenv:
@@ -40,58 +47,38 @@ source venv/bin/activate
4047
pip install -r requirements.txt
4148
```
4249

43-
## Supported commands
44-
45-
| Command | Supported? |
46-
|:---:|:---: |
47-
| enumerate | YES |
48-
| getmasterxpub | YES |
49-
| signtx | YES |
50-
| getxpub | YES |
51-
| signmessage | YES |
52-
| getkeypool | YES |
53-
| getdescriptors | YES |
54-
| displayaddress | YES |
55-
| setup | Planned |
56-
| wipe | Planned |
57-
| restore | Planned |
58-
| backup | Planned |
59-
| promptpin | Planned |
60-
| sendpin | Planned |
61-
62-
| Flag | Supported? |
63-
|:---:|:---:|
64-
| --device-path | YES |
65-
| --device-type | YES |
66-
| --password | Planned |
67-
| --stdinpass | NO |
68-
| --testnet | Planned |
69-
| --debug | Planned |
70-
| --fingerprint | YES |
71-
| --version | Planned |
72-
| --stdin | NO |
73-
| --interactive | Planned |
74-
| --expert | YES |
75-
76-
## Tests
77-
78-
At the moment you'll need a HW plugged in to be able to run tests.
79-
80-
If you don't have a hardware wallet, you can try [coldcard simulator](https://github.com/Coldcard/firmware).
81-
82-
To run tests you should:
83-
84-
- Install requirements and activate the virtualenv, as specified before
85-
- Plug in a HW.
86-
- `cargo test`
87-
88-
## Devices tested
89-
| Device | Tested |
90-
|:---:|:---:|
91-
| Ledger Nano X | NO
92-
| Ledger Nano S | YES
93-
| Trezor One | NO
94-
| Trezor Model T | YES
95-
| Digital BitBox | NO
96-
| KeepKey | NO
97-
| Coldcard | YES
50+
## Usage
51+
52+
```rust
53+
use bitcoin::util::bip32::DerivationPath;
54+
use hwi::error::Error;
55+
use hwi::{interface, types, HWIClient};
56+
use std::str::FromStr;
57+
58+
fn main() -> Result<(), Error> {
59+
let devices = interface::HWIClient::enumerate()?;
60+
let device = devices.first().expect("No devices found");
61+
let client = HWIClient::get_client(
62+
&device,
63+
true,
64+
types::HWIChain::Test,
65+
)?;
66+
let derivation_path = DerivationPath::from_str("m/44'/1'/0'/0/0").unwrap();
67+
let s = client.sign_message("I love BDK wallet", &derivation_path)?;
68+
println!("{:?}", s.signature);
69+
Ok(())
70+
}
71+
```
72+
73+
## Testing
74+
75+
To run the tests, you need to have a hardware wallet plugged in. If you don't have a HW for testing, you can try:
76+
- [Coldcard simulator](https://github.com/Coldcard/firmware)
77+
- [Trezor simulator](https://docs.trezor.io/trezor-firmware/core/emulator/index.html)
78+
- [Ledger simulator](https://github.com/LedgerHQ/speculos)
79+
80+
**Don't use a device with funds for testing!**
81+
82+
Either use a testing device with no funds, or use a simulator.
83+
84+
You can run the tests with `cargo test`.

src/interface.rs

Lines changed: 44 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,17 @@ impl Deref for HWIClient {
5959

6060
impl HWIClient {
6161
/// Lists all HW devices currently connected.
62+
/// ```no_run
63+
/// # use hwi::HWIClient;
64+
/// # use hwi::error::Error;
65+
/// # fn main() -> Result<(), Error> {
66+
/// let devices = HWIClient::enumerate()?;
67+
/// for device in devices {
68+
/// println!("I can see a {} here 😄", device.model);
69+
/// }
70+
/// # Ok(())
71+
/// # }
72+
/// ```
6273
pub fn enumerate() -> Result<Vec<HWIDevice>, Error> {
6374
let libs = HWILib::initialize()?;
6475
Python::with_gil(|py| {
@@ -68,11 +79,28 @@ impl HWIClient {
6879
})
6980
}
7081

71-
/// Finds the Python object of the device corresponding to Device
72-
/// # Arguements
73-
/// * `device` - The device for which the Python object will be passed
74-
/// * `expert` - Whether the device should be opened in expert mode (enables additional output for some actions)
75-
/// * `chain` - The Chain this client will be using
82+
/// Returns the HWIClient for a certain device. You can list all the available devices using
83+
/// [`enumerate`](HWIClient::enumerate).
84+
///
85+
/// Setting `expert` to `true` will enable additional output for some commands.
86+
/// ```
87+
/// # use hwi::HWIClient;
88+
/// # use hwi::types::*;
89+
/// # use hwi::error::Error;
90+
/// # fn main() -> Result<(), Error> {
91+
/// let devices = HWIClient::enumerate()?;
92+
/// for device in devices {
93+
/// let client = HWIClient::get_client(&device, false, HWIChain::Test)?;
94+
/// let xpub = client.get_master_xpub(HWIAddressType::Tap, 0)?;
95+
/// println!(
96+
/// "I can see a {} here, and its xpub is {}",
97+
/// device.model,
98+
/// xpub.to_string()
99+
/// );
100+
/// }
101+
/// # Ok(())
102+
/// # }
103+
/// ```
76104
pub fn get_client(
77105
device: &HWIDevice,
78106
expert: bool,
@@ -92,7 +120,7 @@ impl HWIClient {
92120
})
93121
}
94122

95-
/// Returns the master xpub of a device.
123+
/// Returns the master xpub of a device, given the address type and the account number.
96124
pub fn get_master_xpub(
97125
&self,
98126
addrtype: HWIAddressType,
@@ -109,9 +137,7 @@ impl HWIClient {
109137
})
110138
}
111139

112-
/// Returns a psbt signed.
113-
/// # Arguments
114-
/// * `psbt` - The PSBT to be signed.
140+
/// Signs a PSBT.
115141
pub fn sign_tx(
116142
&self,
117143
psbt: &PartiallySignedTransaction,
@@ -128,10 +154,7 @@ impl HWIClient {
128154
})
129155
}
130156

131-
/// Returns the xpub of a device.
132-
/// # Arguments
133-
/// * `path` - The derivation path to derive the key.
134-
/// * `expert` - Whether the device should be opened in expert mode (enables additional output for some actions)
157+
/// Returns the xpub of a device. If `expert` is set, additional output is returned.
135158
pub fn get_xpub(
136159
&self,
137160
path: &DerivationPath,
@@ -150,9 +173,6 @@ impl HWIClient {
150173
}
151174

152175
/// Signs a message.
153-
/// # Arguments
154-
/// * `message` - The message to sign.
155-
/// * `path` - The derivation path to derive the key.
156176
pub fn sign_message(
157177
&self,
158178
message: &str,
@@ -171,10 +191,10 @@ impl HWIClient {
171191
}
172192

173193
/// Returns an array of keys that can be imported in Bitcoin core using importmulti
174-
/// # Arguments
194+
///
175195
/// * `keypool` - `keypool` value in result. Check bitcoin core importmulti documentation for further information
176196
/// * `internal` - Whether to use internal (change) or external keys
177-
/// * `addr_type` - HWIAddressType to use
197+
/// * `addr_type` - Address type to use
178198
/// * `addr_all` - Whether to return a multiple descriptors for every address type
179199
/// * `account` - Optional BIP43 account to use
180200
/// * `path` - The derivation path to derive the keys.
@@ -218,9 +238,7 @@ impl HWIClient {
218238
})
219239
}
220240

221-
/// Returns device descriptors
222-
/// # Arguments
223-
/// * `account` - Optional BIP43 account to use.
241+
/// Returns device descriptors. You can optionally specify a BIP43 account to use.
224242
pub fn get_descriptors(&self, account: Option<u32>) -> Result<HWIDescriptor, Error> {
225243
Python::with_gil(|py| {
226244
let func_args = (&self.hw_client, account.unwrap_or(0));
@@ -234,9 +252,7 @@ impl HWIClient {
234252
})
235253
}
236254

237-
/// Returns an address given a descriptor.
238-
/// # Arguments
239-
/// * `descriptor` - The descriptor to use. HWI doesn't support descriptors checksums.
255+
/// Returns an address given a descriptor. Note that HWI doesn't support descriptors checksums.
240256
pub fn display_address_with_desc(&self, descriptor: &str) -> Result<HWIAddress, Error> {
241257
Python::with_gil(|py| {
242258
let path = py.None();
@@ -251,10 +267,7 @@ impl HWIClient {
251267
})
252268
}
253269

254-
/// Returns an address given pat and address type
255-
/// # Arguments
256-
/// * `path` - The derivation path to use.
257-
/// * `address_type` - Address type to use.
270+
/// Returns an address given path and address type.
258271
pub fn display_address_with_path(
259272
&self,
260273
path: &DerivationPath,
@@ -274,9 +287,9 @@ impl HWIClient {
274287
}
275288

276289
/// Install the udev rules to the local machine.
277-
/// The rules will be copied from the source to the location.
278-
/// The default source location is "./udev"
279-
/// The default destination location is "/lib/udev/rules.d"
290+
///
291+
/// The rules will be copied from the source to the location; the default source location is
292+
/// `./udev`, the default destination location is `/lib/udev/rules.d`
280293
pub fn install_udev_rules(source: Option<&str>, location: Option<&str>) -> Result<(), Error> {
281294
Python::with_gil(|py| {
282295
let libs = HWILib::initialize()?;

0 commit comments

Comments
 (0)