or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

apdu-communication.mdconfiguration.mddevice-management.mderror-handling.mdevents-lifecycle.mdindex.md
tile.json

device-management.mddocs/

0

# Device Discovery and Connection

1

2

Core functionality for discovering available Ledger devices and establishing transport connections. This includes both one-time device listing and continuous monitoring of device availability through the observer pattern.

3

4

## Capabilities

5

6

### Platform Support Check

7

8

Determines if the transport implementation is supported on the current platform/browser environment.

9

10

```typescript { .api }

11

/**

12

* Statically check if a transport is supported on the user's platform/browser

13

* @returns Promise resolving to true if supported, false otherwise

14

*/

15

static isSupported(): Promise<boolean>;

16

```

17

18

**Usage Example:**

19

20

```javascript

21

import MyTransport from "./my-transport";

22

23

const supported = await MyTransport.isSupported();

24

if (!supported) {

25

throw new Error("This transport is not supported on your platform");

26

}

27

```

28

29

### Device Listing

30

31

Lists all currently available device descriptors in a single snapshot. For real-time device monitoring, use `listen()` instead.

32

33

```typescript { .api }

34

/**

35

* List once all available descriptors. For better granularity, use listen()

36

* @returns Promise of array of descriptors that can be passed to open()

37

*/

38

static list(): Promise<Array<Descriptor>>;

39

```

40

41

**Usage Example:**

42

43

```javascript

44

import MyTransport from "./my-transport";

45

46

// Get all currently connected devices

47

const descriptors = await MyTransport.list();

48

console.log(`Found ${descriptors.length} devices`);

49

50

for (const descriptor of descriptors) {

51

try {

52

const transport = await MyTransport.open(descriptor);

53

// Use transport...

54

await transport.close();

55

} catch (error) {

56

console.error("Failed to open device:", error);

57

}

58

}

59

```

60

61

### Device Event Monitoring

62

63

Continuously monitors for device connection and disconnection events using the observer pattern. This is the recommended approach for responsive device management.

64

65

```typescript { .api }

66

/**

67

* Listen to all device events for a given Transport using observer pattern

68

* @param observer Object with next, error, and complete functions

69

* @returns Subscription object to unsubscribe from events

70

*/

71

static listen(observer: Observer<DescriptorEvent<Descriptor>>): Subscription;

72

```

73

74

**Usage Example:**

75

76

```javascript

77

import MyTransport from "./my-transport";

78

79

const subscription = MyTransport.listen({

80

next: (event) => {

81

if (event.type === "add") {

82

console.log("Device connected:", event.deviceModel?.productName);

83

// Open the device

84

MyTransport.open(event.descriptor).then(transport => {

85

// Device is ready to use

86

console.log("Transport opened successfully");

87

});

88

} else if (event.type === "remove") {

89

console.log("Device disconnected");

90

}

91

},

92

error: (error) => {

93

console.error("Device monitoring error:", error);

94

},

95

complete: () => {

96

console.log("Device monitoring completed");

97

}

98

});

99

100

// Stop listening after 30 seconds

101

setTimeout(() => {

102

subscription.unsubscribe();

103

}, 30000);

104

```

105

106

### Device Connection

107

108

Opens a transport connection to a specific device using its descriptor.

109

110

```typescript { .api }

111

/**

112

* Attempt to create a Transport instance with a descriptor

113

* @param descriptor The descriptor to open the transport with

114

* @param timeout Optional timeout in milliseconds

115

* @returns Promise of Transport instance

116

*/

117

static open(descriptor: Descriptor, timeout?: number): Promise<Transport<Descriptor>>;

118

```

119

120

**Usage Example:**

121

122

```javascript

123

import MyTransport from "./my-transport";

124

125

// Assuming you have a descriptor from list() or listen()

126

const transport = await MyTransport.open(descriptor, 5000); // 5 second timeout

127

128

try {

129

// Set up the transport

130

transport.setScrambleKey("BTC");

131

132

// Use the transport for communication

133

const response = await transport.send(0xB0, 0x01, 0x00, 0x00);

134

135

} finally {

136

// Always close the transport

137

await transport.close();

138

}

139

```

140

141

### Quick Device Creation

142

143

Convenience method that combines listening and opening the first available device. This is a simplified alternative to manually using `listen()` and `open()`.

144

145

```typescript { .api }

146

/**

147

* Create transport by opening the first descriptor available or throw if none found

148

* @param openTimeout Timeout for opening the device (default: 3000ms)

149

* @param listenTimeout Timeout for finding a device (optional)

150

* @returns Promise of Transport instance

151

*/

152

static create(openTimeout?: number = 3000, listenTimeout?: number): Promise<Transport<Descriptor>>;

153

```

154

155

**Usage Example:**

156

157

```javascript

158

import MyTransport from "./my-transport";

159

160

try {

161

// Wait up to 10 seconds to find a device, then 5 seconds to open it

162

const transport = await MyTransport.create(5000, 10000);

163

164

console.log("Connected to device:", transport.deviceModel?.productName);

165

166

// Use the transport

167

transport.setScrambleKey("BTC");

168

const response = await transport.send(0xB0, 0x01, 0x00, 0x00);

169

170

await transport.close();

171

172

} catch (error) {

173

if (error.id === "NoDeviceFound") {

174

console.error("No Ledger device found");

175

} else if (error.id === "ListenTimeout") {

176

console.error("Timeout waiting for device");

177

} else {

178

console.error("Failed to create transport:", error);

179

}

180

}

181

```

182

183

## Types

184

185

### DescriptorEvent

186

187

```typescript { .api }

188

interface DescriptorEvent<Descriptor> {

189

/** Event type: "add" when device connects, "remove" when disconnects */

190

type: "add" | "remove";

191

/** Descriptor that can be passed to open() */

192

descriptor: Descriptor;

193

/** Device model information (Nano S, Nano X, Blue) */

194

deviceModel?: DeviceModel | null;

195

/** Transport-specific device information */

196

device?: Device;

197

}

198

```

199

200

### Observer

201

202

```typescript { .api }

203

interface Observer<Event> {

204

/** Called when a new event occurs */

205

next(event: Event): void;

206

/** Called when an error occurs */

207

error(e: any): void;

208

/** Called when observation completes */

209

complete(): void;

210

}

211

```

212

213

### Subscription

214

215

```typescript { .api }

216

interface Subscription {

217

/** Stop listening to events */

218

unsubscribe(): void;

219

}

220

```

221

222

## Static Error Messages

223

224

The Transport class provides predefined error messages for common scenarios:

225

226

```typescript { .api }

227

class Transport<Descriptor> {

228

/** Error message for device not found scenarios */

229

static ErrorMessage_NoDeviceFound: "No Ledger device found";

230

231

/** Error message for listen timeout scenarios */

232

static ErrorMessage_ListenTimeout: "No Ledger device found (timeout)";

233

}

234

```

235

236

## Error Handling

237

238

Device management operations may throw various errors:

239

240

- **NoDeviceFound**: No devices available when calling `create()`

241

- **ListenTimeout**: Timeout reached while waiting for devices

242

- **TransportOpenUserCancelled**: User cancelled the device selection

243

- **TransportInterfaceNotAvailable**: Transport interface not available on platform