# python-keepkey

`python-keepkey` is the official Python library for communicating with a KeepKey device. It is used by firmware CI to drive emulator tests and can also communicate with a physical device. Coverage and transport must be identified in each run. You can also use it to write scripts, automate testing, or build tooling.

**Repository:** [github.com/keepkey/python-keepkey](https://github.com/keepkey/python-keepkey)

## Installation

```bash
pip install keepkey
```

Or from source:
```bash
git clone https://github.com/keepkey/python-keepkey.git
cd python-keepkey
pip install -e .
```

## Quick start

```python
from keepkeylib.transport_hid import HidTransport
from keepkeylib.client import KeepKeyClient

# Connect to device
transport = HidTransport(HidTransport.enumerate()[0])
client = KeepKeyClient(transport)

# Get device features
features = client.get_features()
print(f"Firmware: {features.major_version}.{features.minor_version}.{features.patch_version}")
print(f"Label: {features.label}")

# Get a Bitcoin address
address = client.get_address('Bitcoin', [0x80000000 + 44, 0x80000000, 0x80000000, 0, 0])
print(f"BTC address: {address}")
```

## CI test structure

The firmware CI organizes tests by chain section. Each test file is named `test_msg_<operation>.py` and lives under `tests/` in the python-keepkey repo.

| Section | Test file pattern |
|---|---|
| Core | `test_msg_wipedevice.py`, `test_msg_resetdevice.py`, `test_msg_changepin.py` ... |
| Bitcoin | `test_msg_getaddress.py`, `test_msg_signtx.py` |
| Ethereum | `test_msg_ethereum_signtx.py`, `test_msg_ethereum_message.py` |
| THORChain | `test_msg_thorchain_signtx.py` |
| Solana | `test_msg_solana_getaddress.py`, `test_msg_solana_signtx.py` |

Each test follows the same pattern:
1. Load a known test mnemonic into the device (debug-only operation)
2. Send the target message
3. Capture OLED frames (if running against emulator with DEBUG_LINK)
4. Verify the returned signature/address against the expected value

## Running tests locally

### Against a real device

```bash
cd python-keepkey
pytest tests/test_msg_signtx.py -v
```

The device must be unlocked. Tests that wipe or reset the device (`test_msg_wipedevice.py`) will destroy any existing seed — run these only on a test device with no real funds.

### Against the emulator

Download the emulator artifact from a CI run or build it yourself:

```bash
# From keepkey-firmware repo
./scripts/build/docker/emulator/release.sh

# Set transport to emulator
export KEEPKEY_TRANSPORT=emulator
export KEEPKEY_EMULATOR_PATH=/path/to/emu.elf

pytest tests/ -v
```

The emulator supports DEBUG_LINK, which allows tests to inject button presses and capture OLED output programmatically. Selected catalog tests use this capture path. See [Test Atlas](/docs/firmware/test-atlas) for scope and limits.

## Generating a test report

The CI's `generate-test-report` job runs `python-keepkey`'s report generator against the test results:

```bash
python scripts/generate_report.py \
  --firmware-version 7.14.1 \
  --test-results results/ \
  --output keepkey-test-report.pdf
```

The report includes:
- Pass/fail summary by section
- Per-test description and OLED captures
- Device info (label, firmware version, seed fingerprint)
- All chain balances and addresses at time of test

Reports generated by CI are publicly available as artifacts from [GitHub Actions](https://github.com/keepkey/keepkey-firmware/actions).

## Key message types

The library wraps the protobuf message protocol. Common messages:

| Python method | Protobuf message | What it does |
|---|---|---|
| `client.get_features()` | `GetFeatures` | Device info, firmware version, features enabled |
| `client.get_address(coin, path)` | `GetAddress` | Derive and display an address |
| `client.ethereum_get_address(path)` | `EthereumGetAddress` | ETH address with EIP-55 checksum |
| `client.sign_tx(coin, inputs, outputs)` | `SignTx` | Sign a Bitcoin-type transaction |
| `client.ethereum_sign_tx(...)` | `EthereumSignTx` | Sign an ETH transaction |
| `client.sign_message(coin, path, msg)` | `SignMessage` | Sign arbitrary message with BTC key |
| `client.recover_device(...)` | `RecoveryDevice` | Initiate cipher-based seed recovery |
| `client.wipe_device()` | `WipeDevice` | Erase all keys and settings |

## Full protocol reference

The protobuf definitions live in [device-protocol](https://github.com/keepkey/device-protocol), pinned by the selected firmware and client. Use matching revisions; a definition alone does not prove that a firmware handler supports the message.

```bash
# In keepkey-firmware repo
ls deps/device-protocol/
# messages.proto          - core messages
# messages-bitcoin.proto  - Bitcoin + forks
# messages-ethereum.proto - Ethereum + ERC-20
# messages-cosmos.proto   - Cosmos/THORChain/Maya
# messages-solana.proto   - Solana
# ...
```

## Related

- [Firmware Overview](/docs/firmware) — build from source, CI pipeline
- [Supported Chains](/docs/firmware/supported-chains) — what operations each chain supports
- [Device Display Reference](/docs/firmware/device-display) — what the OLED shows for each message type
- [REST API](/docs/reference/rest) — higher-level HTTP wrapper (used by the desktop application)
