Use this page to collect the upstream projects and protocol documentation needed to add or maintain support for a hardware wallet in BHWI.
- README: explains the sans-I/O interpreter model used by device integrations.
- VISION: gives the project context and the reason BHWI keeps protocol logic separate from transport I/O.
- Common command interface: lists the device-agnostic commands, responses, recipients, and device-specific context.
- Protocol framing: defines the
Channeltrait and the per-device wire framing carried over it. - Transport crate: implements
Channelover HID, WebUSB, serial, TCP, and emulator sockets, and enumerates the devices found. - CLI crate: shows how command parsing and output formatting sit on top of it.
- BIP 32: hierarchical deterministic keys and derivation paths.
- BIP 44: account structure used by standard descriptors.
- BIP 174: PSBT v0.
- BIP 370: PSBT v2, required by the Ledger Bitcoin app.
- BIP 380 and BIP 388: output descriptors and wallet policies.
- Miniscript: policy language used for descriptor-backed wallet support.
- Bitcoin Core HWI: reference behavior for common hardware wallet commands.
- Async-HWI: earlier Wizardsardine Rust implementation that informed and inspired BHWI.
- Local code (gated behind the
bitboxcargo feature): - Upstream references:
- Onboarding notes:
- BitBox02 traffic rides U2F-HID framing and is encrypted with a Noise channel established during pairing. The simulator auto-confirms pairing.
- Descriptor-based address display re-supplies the wallet policy each time via
DeviceContext::BitBox; the device holds no persistent policy token like a Ledger HMAC. - Wallet policies share the miniscript
WalletPolicyextraction inbhwi/src/policy.rswith the Ledger backend. - Use these commands for emulator-backed tests:
nix run .#bitbox
nix develop .#bitbox -c cargo test -p bhwi-e2e-bitbox -- --test-threads=1- Local code (gated behind the
ledgercargo feature): - Upstream references:
- Onboarding notes:
- Ledger uses APDUs and device-requested client callbacks for wallet policy merkle data and PSBT signing data.
- Keep wallet policy formatting aligned with BIP 388 and the Ledger Bitcoin app's expected key-info strings.
- Use these commands for emulator-backed tests:
nix run .#ledger
nix develop .#ledger -c cargo test -p bhwi-e2e-ledger -- --test-threads=1- Local code (gated behind the
coldcardcargo feature): - Upstream references:
- Onboarding notes:
- Coldcard commands are encrypted after the initial public-key exchange.
- The simulator exposes
/tmp/ckcc-simulator.sock; the local device ID also records this emulator path. - Use these commands for emulator-backed tests:
nix run .#coldcard
nix develop .#coldcard -c cargo test -p bhwi-e2e-coldcard -- --test-threads=1- Local code (gated behind the
jadecargo feature): - Upstream references:
- Onboarding notes:
- Jade uses CBOR-RPC requests over serial/TCP.
- Authentication may require forwarding a device-provided HTTP request to the pinserver before completing the device handshake.
- Use these commands for emulator-backed tests:
nix run .#jade-pinserver
nix run .#jade
nix run .#jade-init
nix develop .#jade -c cargo test -p bhwi-e2e-jade -- --test-threads=1- Local code (gated behind the
trezorcargo feature): - Upstream references:
- Onboarding notes:
- Messages are protobuf framed as
##, a big-endian message type and length, then chunked into 64 byte reports prefixed with0x3f. The framing is the same over HID, WebUSB and the UDP emulator, so one transport serves all three. - The generated bindings are vendored and regenerated from the pinned firmware revision, matching the revision the emulators are built from.
GetPublicKeysetsignore_xpub_magicso the device returns standard xpub/tpub rather than SLIP-132 prefixes.- The Trezor One and the Model T run different firmware codebases, so each model has its own emulator.
- The browser transports split the same way the native ones do. The Trezor One
is an HID device, so it uses
bhwi-wasm/src/webhid.rswith the vendor usage page0xff00. The Model T exposes a USB vendor interface instead, so it usesbhwi-wasm/src/webusb.rs. - Use these commands for emulator-backed tests:
- Messages are protobuf framed as
nix run .#trezor-one # or nix run .#trezor-t
nix run .#trezor-init
nix develop .#trezor -c cargo test -p bhwi-e2e-trezor -- --test-threads=1- Local code (gated behind the
keepkeycargo feature): - Upstream references:
- KeepKey firmware pinned to
v7.10.0 commit
d54797ee604f12c82ac6e5e02490b62dc04bf2dd - KeepKey device protocol pinned
through the firmware submodule at
323802f17dd44165a5100357df771348c8b49672 - Bitcoin Core HWI 3.2.0 KeepKey backend
- KeepKey firmware pinned to
v7.10.0 commit
- Onboarding notes:
- KeepKey shares Trezor's protocol-v1 report framing, but it is a separate profile with its own protobuf deltas, command rules, USB IDs, emulator, host passphrase behavior, management state machine, and capability limits.
- Native discovery uses HID
2b24:0001on usage page0xff00, WebUSB2b24:0002, and emulator UDP127.0.0.1:11044; the debug link is UDP11045. - PIN entry and recovery-character entry are host interactions. Restore uses KeepKey firmware's character cipher; pinned Python HWI has no working reference-tested restore flow.
- The recursively pinned firmware and separately pinned nanopb tree are
copied to a writable cache and patched with HWI's
test/data/keepkey-build.patchat the firmware root,test/data/keepkey-googletest.patchat the firmware'sdeps/googletestroot, andtest/data/nanopb-deprecated-mode.patchat the nanopb root. BHWI additionally appliesnix/patches/keepkey/cmake-minimum.patchat the firmware root. The emulator outputs are currentlyx86_64-linuxonly. - Use these commands for emulator-backed tests:
nix run .#keepkey
nix run .#keepkey-init
nix develop .#keepkey -c cargo test -p bhwi-e2e-keepkey -- --test-threads=1
nix run .#hwi-upstream-keepkey- Start from
bhwi/src/common.rsand map each supported common command to the device protocol. - Declare a cargo feature for the device in
bhwi(gating its module, adapter, and any device-specific dependencies) and forward it frombhwi-async. - Keep protocol encoding, response parsing, authentication, and intermediate device callbacks inside the device interpreter.
- Keep USB, serial, TCP, browser, and emulator I/O in transport crates or clients, not in the interpreter.
- Add emulator or simulator notes under
docs/when an upstream test target is available. - Add focused unit tests for protocol encoding/parsing and e2e coverage for commands that need an emulator.