Lux Docs
Lux Skills Reference

Lux Ledger - Hardware Wallet Integration

Documentation for Lux Ledger - Hardware Wallet Integration

Overview

Lux Ledger (github.com/luxfi/ledger) is a Go client library for interacting with the Lux app on Ledger hardware wallets (Nano S, Nano X, Nano S Plus, Stax, Flex). It implements the APDU protocol over USB HID for key derivation (BIP32/BIP44), address generation, transaction signing, hash signing, and multi-signature support. The repository also contains the Rust source for the Ledger app itself in /rust/.

When to use

  • Integrating Ledger hardware wallet signing into Go applications
  • Implementing the keychain.Ledger interface for wallet/signing flows
  • Building or modifying the Ledger app firmware (Rust, in /rust/)
  • Debugging Ledger device communication issues (APDU protocol)
  • Adding new Ledger device model support

Hard requirements

  1. ALWAYS use github.com/luxfi/* packages -- NEVER go-ethereum or luxfi
  2. NEVER bump Go package versions above v1.x.x
  3. Tests require a physical Ledger device with the Lux app installed and unlocked
  4. HRP (human-readable part) must be <= 83 characters
  5. Build tags: ledger_mock and ledger_zemu exclude real HID transport

Quick reference

ItemValue
Modulegithub.com/luxfi/ledger
Go1.26.1
LicenseApache 2.0
Package TypeLibrary (no binary)
Default HRPlux
Derivation Pathm/44'/60'/0' (Ethereum-compatible)
Default Chain ID2q9e4r6Mu3U68nU1fYjgbR6JvwrRx36CohpAX5UQxse55x1Q5
Ledger App CLA0x80

Core Concepts

Entry Points

// Recommended: implements keychain.Ledger interface
ledger, err := ledger.NewLedger()
defer ledger.Disconnect()

// Or directly
app, err := ledger.FindLedgerLuxApp()
defer app.Close()

keychain.Ledger Interface

The library implements the keychain.Ledger interface for seamless wallet integration:

MethodSignaturePurpose
Address(hrp string, index uint32) (ids.ShortID, error)Get address at derivation index
GetAddresses(indices []uint32) ([]ids.ShortID, error)Get multiple addresses
Sign(message []byte, index uint32) ([]byte, error)Sign raw message
SignHash(hash []byte, index uint32) ([]byte, error)Sign pre-hashed data (32 bytes)
SignTransaction(hash []byte, indices []uint32) ([][]byte, error)Multi-address transaction signing
Disconnect() errorClose device connection

Low-Level API

MethodPurpose
GetVersion()Get app version (major.minor.patch)
GetPubKey(path, show, hrp, chainID)Get public key, hash, and bech32 address
SignFull(pathPrefix, signerPaths, message, changePaths)Sign full transaction with multiple paths
SignHashFull(pathPrefix, signerPaths, hash)Sign a 32-byte hash with multiple paths
VerifyMultipleSignatures(resp, hash, rootPath, paths, hrp, chainID)Verify all signatures from a multi-sign

APDU Instructions

InstructionCodePurpose
INS_GET_VERSION0x00Get app version
INS_WALLET_ID0x01Get wallet identifier
INS_GET_ADDR0x02Get address/pubkey
INS_GET_EXTENDED_PUBLIC_KEY0x03Get extended public key
INS_SIGN_HASH0x04Sign a hash
INS_SIGN0x05Sign a transaction
INS_SIGN_MSG0x06Sign a message

Supported Devices

DeviceProduct ID (high byte)Interface
Ledger Nano S0x100
Ledger Nano X0x400
Ledger Nano S Plus0x500
Ledger Stax0x600
Ledger Flex0x700

All use USB HID with vendor ID 0x2c97, channel 0x0101, packet size 64 bytes.

Signature Verification

Uses btcec/v2 secp256k1 ECDSA verification with malleable signature rejection:

// 64-byte [R || S] format
ok := ledger.VerifySignature(pubkey, hash, signature)

Key Dependencies

github.com/luxfi/hid@v0.9.3       -- USB HID device access
github.com/luxfi/ids@v1.2.9       -- Lux ID types (ShortID)
github.com/luxfi/crypto@v1.17.38  -- Cryptographic primitives
github.com/btcsuite/btcd/btcec/v2 -- secp256k1 ECDSA
github.com/mr-tron/base58         -- Base58 encoding (chain IDs)
go.uber.org/zap                    -- Structured logging
github.com/stretchr/testify       -- Test assertions

File Structure

ledger/
  lux.go           -- Main API: FindLedgerLuxApp, keychain.Ledger impl
  types.go         -- LedgerLux, VersionInfo, ResponseSign, ResponseAddr
  common.go        -- Path/HRP/ChainID serialization, signature helpers
  hid.go           -- USB HID transport (LedgerAdmin, LedgerDevice)
  apdu.go          -- APDU command wrapping/unwrapping
  logger.go        -- zap-based logger (LEDGER_LOG_LEVEL env)
  lux_test.go      -- Integration tests (require physical device)
  common_test.go   -- Unit tests (path serialization, version check)
  rust/            -- Ledger app source (Rust workspace)
    app/           -- Main Ledger app crate
    app-derive/    -- Derive macros
    Cargo.toml     -- Workspace config (resolver v2)
    deps/          -- Build dependencies
    hfuzz/         -- Fuzz testing
    zemu/          -- Zemu device emulator tests
  docs/            -- Documentation
  go-docs/         -- Go-specific documentation

Rust Ledger App

The /rust/ directory contains the Ledger app firmware:

  • Workspace with app and app-derive crates
  • Build profiles: dev (abort on panic), release (size-optimized, opt-level = "z")
  • Testing via Zemu emulator and Miri
  • Fuzz testing via cargo-hfuzz
  • Build: make (requires BOLOS SDK or Docker via deps/dockerized_build.mk)

Build and Test

# Go library (unit tests, no device needed)
go test -short ./...

# Go library (full tests, requires Ledger device)
go test -v ./...

# Rust Ledger app
cd rust && cargo build
cd rust && cargo test

# Zemu emulator tests
cd rust/zemu && yarn test

# Fuzz testing
cd rust/hfuzz && cargo hfuzz run apdu

Logging

Set LEDGER_LOG_LEVEL environment variable: debug, info (default), warn, error.

Troubleshooting

IssueCauseSolution
device not foundNo Ledger connected or lockedConnect device, unlock, open Lux app
CLA not supportedLux app not open on deviceOpen the Lux app on the Ledger
APDU commands < 5Malformed commandCheck message construction
timeout reading from deviceDevice busy or unresponsiveDisconnect and reconnect, 20s timeout
wrong hash sizeHash not 32 bytesPass SHA-256 digest (32 bytes)
invalid pathBad BIP32 path formatUse format m/44'/60'/0'/0/0
read channel closedUSB connection droppedReconnect device
Version required errorApp version too oldUpdate Ledger app firmware
  • lux/lux-wallet.md -- Wallet implementation (uses ledger as signing backend)
  • lux/lux-hsm.md -- HSM integration (software signing alternative)
  • lux/lux-crypto.md -- Cryptographic primitives

On this page