0
# Ledger Hardware Wallet Transport
1
2
@ledgerhq/hw-transport provides the foundational transport layer interface for Ledger Hardware Wallet communication, serving as the base abstraction that enables different transport implementations (USB, Bluetooth, WebUSB, etc.) to communicate with Ledger devices. It defines the core Transport class with essential methods for device discovery, connection management, and APDU (Application Protocol Data Unit) exchange, including features like event-driven device detection, timeout management, debug logging, and scramble key handling for secure communication.
3
4
## Package Information
5
6
- **Package Name**: @ledgerhq/hw-transport
7
- **Package Type**: npm
8
- **Language**: JavaScript/TypeScript (Flow types)
9
- **Installation**: `npm install @ledgerhq/hw-transport`
10
11
## Core Imports
12
13
```javascript
14
import Transport, {
15
TransportError,
16
TransportStatusError,
17
StatusCodes,
18
getAltStatusMessage
19
} from "@ledgerhq/hw-transport";
20
```
21
22
For Flow projects:
23
24
```javascript
25
import Transport, {
26
TransportError,
27
TransportStatusError,
28
StatusCodes,
29
getAltStatusMessage,
30
type Subscription,
31
type Device,
32
type DescriptorEvent,
33
type Observer
34
} from "@ledgerhq/hw-transport";
35
```
36
37
## Basic Usage
38
39
```javascript
40
import Transport from "@ledgerhq/hw-transport";
41
42
// Example with a hypothetical USB transport implementation
43
class MyUSBTransport extends Transport {
44
// Implementation would provide specific transport logic
45
}
46
47
// Check if transport is supported
48
const isSupported = await MyUSBTransport.isSupported();
49
if (!isSupported) {
50
throw new Error("Transport not supported");
51
}
52
53
// Create transport instance
54
const transport = await MyUSBTransport.create();
55
56
// Set scramble key for secure communication
57
transport.setScrambleKey("BTC");
58
59
// Send APDU command (example: get app version)
60
const response = await transport.send(0xB0, 0x01, 0x00, 0x00);
61
62
// Listen for disconnect events
63
transport.on("disconnect", () => {
64
console.log("Device disconnected");
65
});
66
67
// Close when done
68
await transport.close();
69
```
70
71
## Architecture
72
73
The Transport class serves as an abstract base class that defines the standard interface for all Ledger hardware wallet communication:
74
75
- **Abstract Base Class**: Transport provides the interface specification that concrete implementations must extend
76
- **Observer Pattern**: Device discovery uses the observer pattern for real-time device events
77
- **Event-driven Communication**: Built on EventEmitter for handling connection state changes
78
- **APDU Protocol**: Implements the Application Protocol Data Unit standard for hardware wallet communication
79
- **Atomic Operations**: Ensures thread-safe communication with race condition protection
80
- **Scramble Key Security**: Provides encryption key management for secure app-specific communication
81
82
## Capabilities
83
84
### Device Discovery and Connection
85
86
Core functionality for discovering available Ledger devices and establishing transport connections. Includes both one-time listing and continuous monitoring of device availability.
87
88
```typescript { .api }
89
static isSupported(): Promise<boolean>;
90
static list(): Promise<Array<Descriptor>>;
91
static listen(observer: Observer<DescriptorEvent<Descriptor>>): Subscription;
92
static open(descriptor: Descriptor, timeout?: number): Promise<Transport<Descriptor>>;
93
static create(openTimeout?: number = 3000, listenTimeout?: number): Promise<Transport<Descriptor>>;
94
```
95
96
[Device Management](./device-management.md)
97
98
### APDU Communication
99
100
Low-level and high-level methods for sending Application Protocol Data Units to the Ledger device, including error handling and status code management.
101
102
```typescript { .api }
103
exchange(apdu: Buffer): Promise<Buffer>;
104
send(cla: number, ins: number, p1: number, p2: number, data?: Buffer, statusList?: Array<number>): Promise<Buffer>;
105
```
106
107
[APDU Communication](./apdu-communication.md)
108
109
### Configuration and Security
110
111
Methods for configuring transport behavior, timeouts, and security settings including scramble key management for app-specific encryption.
112
113
```typescript { .api }
114
setScrambleKey(key: string): void;
115
setExchangeTimeout(exchangeTimeout: number): void;
116
setExchangeUnresponsiveTimeout(unresponsiveTimeout: number): void;
117
setDebugMode(): void;
118
```
119
120
[Configuration](./configuration.md)
121
122
### Event Handling and Connection Management
123
124
Event-driven architecture for handling device state changes, connection management, and cleanup operations.
125
126
```typescript { .api }
127
on(eventName: string, cb: Function): void;
128
off(eventName: string, cb: Function): void;
129
close(): Promise<void>;
130
```
131
132
[Events and Lifecycle](./events-lifecycle.md)
133
134
### Error Handling
135
136
Comprehensive error classes for handling transport-specific and device status errors with detailed error codes and messages.
137
138
```typescript { .api }
139
class TransportError extends Error {
140
constructor(message: string, id: string);
141
}
142
143
class TransportStatusError extends Error {
144
constructor(statusCode: number);
145
statusCode: number;
146
statusText: string;
147
}
148
```
149
150
[Error Handling](./error-handling.md)
151
152
## Types
153
154
### Core Transport Types
155
156
```javascript { .api }
157
type Subscription = { unsubscribe: () => void };
158
159
type Device = Object;
160
161
type DescriptorEvent<Descriptor> = {
162
type: "add" | "remove",
163
descriptor: Descriptor,
164
deviceModel?: ?DeviceModel,
165
device?: Device,
166
};
167
168
type Observer<Event> = $ReadOnly<{
169
next: (event: Event) => mixed,
170
error: (e: any) => mixed,
171
complete: () => mixed,
172
}>;
173
```
174
175
### Device Model Types
176
177
```javascript { .api }
178
// DeviceModelId represents the keys of the devices object: "blue", "nanoS", "nanoX"
179
type DeviceModelId = $Keys<typeof devices>;
180
181
type DeviceModel = {
182
id: DeviceModelId,
183
productName: string,
184
productIdMM: number,
185
legacyUsbProductId: number,
186
usbOnly: boolean,
187
memorySize: number,
188
getBlockSize: (firmwareVersion: string) => number,
189
bluetoothSpec?: Array<{
190
serviceUuid: string,
191
writeUuid: string,
192
notifyUuid: string,
193
}>,
194
};
195
```
196
197
### Status Codes
198
199
```javascript { .api }
200
const StatusCodes = {
201
PIN_REMAINING_ATTEMPTS: 0x63c0,
202
INCORRECT_LENGTH: 0x6700,
203
MISSING_CRITICAL_PARAMETER: 0x6800,
204
COMMAND_INCOMPATIBLE_FILE_STRUCTURE: 0x6981,
205
SECURITY_STATUS_NOT_SATISFIED: 0x6982,
206
CONDITIONS_OF_USE_NOT_SATISFIED: 0x6985,
207
INCORRECT_DATA: 0x6a80,
208
NOT_ENOUGH_MEMORY_SPACE: 0x6a84,
209
REFERENCED_DATA_NOT_FOUND: 0x6a88,
210
FILE_ALREADY_EXISTS: 0x6a89,
211
INCORRECT_P1_P2: 0x6b00,
212
INS_NOT_SUPPORTED: 0x6d00,
213
CLA_NOT_SUPPORTED: 0x6e00,
214
TECHNICAL_PROBLEM: 0x6f00,
215
OK: 0x9000,
216
MEMORY_PROBLEM: 0x9240,
217
NO_EF_SELECTED: 0x9400,
218
INVALID_OFFSET: 0x9402,
219
FILE_NOT_FOUND: 0x9404,
220
INCONSISTENT_FILE: 0x9408,
221
ALGORITHM_NOT_SUPPORTED: 0x9484,
222
INVALID_KCV: 0x9485,
223
CODE_NOT_INITIALIZED: 0x9802,
224
ACCESS_CONDITION_NOT_FULFILLED: 0x9804,
225
CONTRADICTION_SECRET_CODE_STATUS: 0x9808,
226
CONTRADICTION_INVALIDATION: 0x9810,
227
CODE_BLOCKED: 0x9840,
228
MAX_VALUE_REACHED: 0x9850,
229
GP_AUTH_FAILED: 0x6300,
230
LICENSING: 0x6f42,
231
HALTED: 0x6faa,
232
};
233
```