#hid #bluetooth #usb-hid #ledger #ledger-hardware #hardware-wallet #wallet

nightly ledger-lib

Communication library for Ledger hardware wallets

1 unstable release

0.1.0 Jun 16, 2023

#1868 in Hardware support

Download history 23/week @ 2024-07-08 26/week @ 2024-07-15 8/week @ 2024-07-22 8/week @ 2024-07-29 61/week @ 2024-08-05 2/week @ 2024-08-12 14/week @ 2024-08-19 15/week @ 2024-08-26 32/week @ 2024-09-02 75/week @ 2024-09-09 80/week @ 2024-09-16 65/week @ 2024-09-23 18/week @ 2024-09-30 55/week @ 2024-10-07 6/week @ 2024-10-14

146 downloads per month
Used in 2 crates

Apache-2.0

82KB
1.5K SLoC

A Ledger hardware wallet communication library

[Device] provides a high-level API for exchanging APDUs with Ledger devices using the [ledger_proto] traits. This is suitable for extension with application-specific interface traits, and automatically implemented over [Exchange] for low-level byte exchange with devices.

[LedgerProvider] and [LedgerHandle] provide a high-level tokio-compatible [Transport] for application integration, supporting connecting to and interacting with ledger devices. This uses a pinned thread to avoid thread safety issues with hidapi and async executors.

Low-level [Transport] implementations are provided for USB/HID, BLE and TCP, with a Generic implementation providing a common interface over all enabled transports.

Safety

Transports are currently marked as Send due to limitations of [async_trait] and are NOT all thread safe. If you're calling this from an async context, please use [LedgerProvider].

This will be corrected when the unstable async trait feature is stabilised, which until then can be opted-into using the unstable_async_trait feature

Examples

use ledger_lib::{LedgerProvider, Filters, Transport, Device, DEFAULT_TIMEOUT};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Fetch provider handle
    let mut provider = LedgerProvider::init().await;

    // List available devices
    let devices = provider.list(Filters::Any).await?;

    // Check we have -a- device to connect to
    if devices.is_empty() {
        return Err(anyhow::anyhow!("No devices found"));
    }

    // Connect to the first device
    let mut ledger = provider.connect(devices[0].clone()).await?;

    // Request device information
    let info = ledger.app_info(DEFAULT_TIMEOUT).await?;
    println!("info: {info:?}");

    Ok(())
}

Dependencies

~9–42MB
~603K SLoC