Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG-npm.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# Changelog

## [Unreleased]
## 0.10.0
- Add `bip85AppBip39()`
- Add support for BitBox02 Nova

## 0.9.1
- WebHID: Automatically connect to a previoulsy connected device
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG-rust.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Changelog

## 0.9.0
- Add support for BitBox02 Nova

## 0.8.0
- Add `bip85_app_bip39()`
- Make the `simulator` feature work with the `multithreaded` feature
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
[package]
name = "bitbox-api"
authors = ["Marko Bencun <[email protected]>"]
version = "0.8.0"
version = "0.9.0"
homepage = "https://bitbox.swiss/"
repository = "https://github.com/BitBoxSwiss/bitbox-api-rs/"
readme = "README-rust.md"
edition = "2021"
license = "Apache-2.0"
description = "A library to interact with the BitBox02 hardware wallet"
description = "A library to interact with BitBox hardware wallets"
keywords = ["bitbox", "api", "bitcoin", "wasm"]
categories = ["api-bindings", "cryptography"]

Expand Down
2 changes: 1 addition & 1 deletion ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ features=(
examples=(
"--example singlethreaded --features=usb,tokio/rt,tokio/macros"
"--example multithreaded --features=usb,tokio/rt,tokio/macros,tokio/rt-multi-thread,multithreaded"
" --example btc_signtx --features=usb,tokio/rt,tokio/macros"
"--example btc_signtx --features=usb,tokio/rt,tokio/macros"
"--example btc_sign_psbt --features=usb,tokio/rt,tokio/macros"
"--example btc_sign_msg --features=usb,tokio/rt,tokio/macros"
"--example btc_miniscript --features=usb,tokio/rt,tokio/macros"
Expand Down
2 changes: 1 addition & 1 deletion sandbox/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/cardano.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ impl<R: Runtime> PairedBitBox<R> {

/// Does this device support Cardano functionality? Currently this means BitBox02 Multi.
pub fn cardano_supported(&self) -> bool {
matches!(self.product(), crate::Product::BitBox02Multi)
self.is_multi_edition()
}

/// Query the device for xpubs. The result contains one xpub per requested keypath. Each xpub is
Expand Down
5 changes: 5 additions & 0 deletions src/communication.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ pub enum Product {
Unknown,
BitBox02Multi,
BitBox02BtcOnly,
BitBox02NovaMulti,
BitBox02NovaBtcOnly,
}

#[derive(Debug)]
Expand Down Expand Up @@ -187,6 +189,7 @@ async fn get_info(communication: &dyn ReadWrite) -> Result<Info, Error> {

let version = semver::Version::parse(version_str).or(Err(Error::Info))?;
const PLATFORM_BITBOX02: u8 = 0x00;
const PLATFORM_BITBOX02_NOVA: u8 = 0x02;
const BITBOX02_EDITION_MULTI: u8 = 0x00;
const BITBOX02_EDITION_BTCONLY: u8 = 0x01;
let platform_byte = *response.first().ok_or(Error::Info)?;
Expand All @@ -198,6 +201,8 @@ async fn get_info(communication: &dyn ReadWrite) -> Result<Info, Error> {
product: match (platform_byte, edition_byte) {
(PLATFORM_BITBOX02, BITBOX02_EDITION_MULTI) => Product::BitBox02Multi,
(PLATFORM_BITBOX02, BITBOX02_EDITION_BTCONLY) => Product::BitBox02BtcOnly,
(PLATFORM_BITBOX02_NOVA, BITBOX02_EDITION_MULTI) => Product::BitBox02NovaMulti,
(PLATFORM_BITBOX02_NOVA, BITBOX02_EDITION_BTCONLY) => Product::BitBox02NovaBtcOnly,
_ => Product::Unknown,
},
unlocked: match unlocked_byte {
Expand Down
2 changes: 1 addition & 1 deletion src/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ impl<R: Runtime> PairedBitBox<R> {

/// Does this device support ETH functionality? Currently this means BitBox02 Multi.
pub fn eth_supported(&self) -> bool {
matches!(self.product(), crate::Product::BitBox02Multi)
self.is_multi_edition()
}

/// Query the device for an xpub.
Expand Down
7 changes: 7 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,13 @@ impl<R: Runtime> PairedBitBox<R> {
self.communication.info.product
}

fn is_multi_edition(&self) -> bool {
matches!(
self.product(),
crate::Product::BitBox02Multi | crate::Product::BitBox02NovaMulti
)
}

/// Returns the firmware version.
pub fn version(&self) -> &semver::Version {
&self.communication.info.version
Expand Down
8 changes: 8 additions & 0 deletions src/u2fframing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,13 @@ pub fn generate_cid() -> u32 {

// U2FWS (U2F WebSocket framing protocol) writes u2fhid header and payload as single package (up to
// 7+7609 bytes)
#[cfg(feature = "wasm")]
pub struct U2fWs {
cid: u32,
cmd: u8,
}

#[cfg(feature = "wasm")]
impl U2fWs {
pub fn new(cmd: u8) -> Self {
U2fWs {
Expand All @@ -102,12 +104,14 @@ impl U2fWs {
}
}

#[cfg(feature = "wasm")]
impl Default for U2fWs {
fn default() -> Self {
Self::new(0)
}
}

#[cfg(feature = "wasm")]
impl U2FFraming for U2fWs {
fn encode(&self, message: &[u8], mut buf: &mut [u8]) -> io::Result<usize> {
let len = encode_header_init(self.cid, self.cmd, message.len() as u16, buf)?;
Expand Down Expand Up @@ -314,6 +318,7 @@ mod tests {
assert_eq!(&data[..], &payload[..]);
}

#[cfg(feature = "wasm")]
#[test]
fn test_u2fws_encode_single() {
let codec = U2fWs::with_cid(0xEEEEEEEE, 0x55);
Expand All @@ -326,6 +331,7 @@ mod tests {
);
}

#[cfg(feature = "wasm")]
#[test]
fn test_u2fws_encode_multi() {
let payload: Vec<u8> = (0..65u8).collect();
Expand All @@ -339,6 +345,7 @@ mod tests {
assert_eq!(&data[..len], &expect[..]);
}

#[cfg(feature = "wasm")]
#[test]
fn test_u2fws_decode_single() {
let codec = U2fWs::with_cid(0xEEEEEEEE, 0x55);
Expand All @@ -349,6 +356,7 @@ mod tests {
assert_eq!(&data[..], b"\x01\x02\x03\x04");
}

#[cfg(feature = "wasm")]
#[test]
fn test_u2fws_decode_multi() {
let payload: Vec<u8> = (0..65u8).collect();
Expand Down
23 changes: 15 additions & 8 deletions src/usb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,15 @@ use std::sync::Mutex;

use super::communication::{Error as CommunicationError, ReadWrite};

/// The hid product string of the multi edition firmware.
const FIRMWARE_PRODUCT_STRING_MULTI: &str = "BitBox02";
/// The hid product string of the btc-only edition firmware.
const FIRMWARE_PRODUCT_STRING_BTCONLY: &str = "BitBox02BTC";
/// The hid product string of the BitBox02 multi edition firmware.
const FIRMWARE_PRODUCT_STRING_BITBOX02_MULTI: &str = "BitBox02";
/// The hid product string of the BitBox02 btc-only edition firmware.
const FIRMWARE_PRODUCT_STRING_BITBOX02_BTCONLY: &str = "BitBox02BTC";

/// The hid product string of the BitBox02 Nova multi edition firmware.
const FIRMWARE_PRODUCT_STRING_BITBOX02_NOVA_MULTI: &str = "BitBox02 Nova Multi";
/// The hid product string of the BitBox02 Nova btc-only edition firmware.
const FIRMWARE_PRODUCT_STRING_BITBOX02_NOVA_BTCONLY: &str = "BitBox02 Nova BTC-only";

#[cfg(feature = "multithreaded")]
pub(crate) struct HidDevice(Mutex<hidapi::HidDevice>);
Expand Down Expand Up @@ -75,10 +80,12 @@ pub enum UsbError {
pub fn is_bitbox02(device_info: &hidapi::DeviceInfo) -> bool {
(matches!(
device_info.product_string(),
Some(FIRMWARE_PRODUCT_STRING_MULTI)
) || matches!(
device_info.product_string(),
Some(FIRMWARE_PRODUCT_STRING_BTCONLY)
Some(
FIRMWARE_PRODUCT_STRING_BITBOX02_MULTI
| FIRMWARE_PRODUCT_STRING_BITBOX02_BTCONLY
| FIRMWARE_PRODUCT_STRING_BITBOX02_NOVA_MULTI
| FIRMWARE_PRODUCT_STRING_BITBOX02_NOVA_BTCONLY
)
)) && device_info.vendor_id() == VENDOR_ID
&& device_info.product_id() == PRODUCT_ID
&& (device_info.usage_page() == 0xffff || device_info.interface_number() == 0)
Expand Down
4 changes: 4 additions & 0 deletions src/wasm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,10 @@ impl PairedBitBox {
crate::Product::Unknown => JsValue::from_str("unknown").into(),
crate::Product::BitBox02Multi => JsValue::from_str("bitbox02-multi").into(),
crate::Product::BitBox02BtcOnly => JsValue::from_str("bitbox02-btconly").into(),
crate::Product::BitBox02NovaMulti => JsValue::from_str("bitbox02-nova-multi").into(),
crate::Product::BitBox02NovaBtcOnly => {
JsValue::from_str("bitbox02-nova-btconly").into()
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/wasm/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ extern "C" {
#[wasm_bindgen(typescript_custom_section)]
const TS_TYPES: &'static str = r#"
type OnCloseCb = undefined | (() => void);
type Product = 'unknown' | 'bitbox02-multi' | 'bitbox02-btconly';
type Product = 'unknown' | 'bitbox02-multi' | 'bitbox02-btconly' | 'bitbox02-nova-multi' | 'bitbox02-nova-btconly';
type BtcCoin = 'btc' | 'tbtc' | 'ltc' | 'tltc' | 'rbtc';
type BtcFormatUnit = 'default' | 'sat';
type XPubType = 'tpub' | 'xpub' | 'ypub' | 'zpub' | 'vpub' | 'upub' | 'Vpub' | 'Zpub' | 'Upub' | 'Ypub';
Expand Down