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

configuration.mddocs/

0

# Configuration and Security

1

2

Methods for configuring transport behavior, timeouts, and security settings. This includes scramble key management for app-specific encryption, timeout configuration for communication reliability, and debug settings.

3

4

## Capabilities

5

6

### Scramble Key Management

7

8

Sets the encryption key used for secure communication with specific Ledger applications. Each app typically has its own scramble key for security isolation.

9

10

```typescript { .api }

11

/**

12

* Set the "scramble key" for the next exchanges with the device

13

* Each App can have a different scramble key and they internally set it at instantiation

14

* @param key The scramble key string

15

*/

16

setScrambleKey(key: string): void;

17

```

18

19

**Usage Example:**

20

21

```javascript

22

import Transport from "@ledgerhq/hw-transport";

23

24

const transport = await MyTransport.create();

25

26

// Set scramble key for Bitcoin app

27

transport.setScrambleKey("BTC");

28

29

// Now all APDU exchanges will use the Bitcoin scramble key

30

const response = await transport.send(0xE0, 0x40, 0x00, 0x00);

31

32

// Switch to Ethereum app

33

transport.setScrambleKey("ETH");

34

const ethResponse = await transport.send(0xE0, 0x02, 0x00, 0x00);

35

```

36

37

**Common Scramble Keys:**

38

- `"BTC"` - Bitcoin and Bitcoin-based cryptocurrencies

39

- `"ETH"` - Ethereum and ERC-20 tokens

40

- `"XRP"` - Ripple

41

- `"ADA"` - Cardano

42

- `""` (empty string) - No scrambling (for system commands)

43

44

### Exchange Timeout Configuration

45

46

Controls how long to wait for APDU command responses before timing out. This helps prevent hanging operations when devices become unresponsive.

47

48

```typescript { .api }

49

/**

50

* Set a timeout (in milliseconds) for the exchange call

51

* Only some transport implementations might implement it (e.g. U2F)

52

* @param exchangeTimeout Timeout in milliseconds

53

*/

54

setExchangeTimeout(exchangeTimeout: number): void;

55

```

56

57

**Usage Example:**

58

59

```javascript

60

const transport = await MyTransport.create();

61

62

// Set 10 second timeout for slow operations

63

transport.setExchangeTimeout(10000);

64

65

// This command will timeout after 10 seconds if no response

66

try {

67

const response = await transport.send(0xE0, 0x04, 0x00, 0x00, transactionData);

68

} catch (error) {

69

// Handle timeout or other errors

70

console.error("Command timed out or failed:", error);

71

}

72

73

// Reset to default timeout (30 seconds)

74

transport.setExchangeTimeout(30000);

75

```

76

77

### Unresponsive Detection Timeout

78

79

Configures how long to wait before emitting "unresponsive" events when a device stops responding during operations.

80

81

```typescript { .api }

82

/**

83

* Define the delay before emitting "unresponsive" on an exchange that does not respond

84

* @param unresponsiveTimeout Timeout in milliseconds

85

*/

86

setExchangeUnresponsiveTimeout(unresponsiveTimeout: number): void;

87

```

88

89

**Usage Example:**

90

91

```javascript

92

const transport = await MyTransport.create();

93

94

// Monitor for unresponsiveness after 5 seconds

95

transport.setExchangeUnresponsiveTimeout(5000);

96

97

// Listen for unresponsive events

98

transport.on("unresponsive", () => {

99

console.warn("Device appears unresponsive - please check connection");

100

// Show user feedback about unresponsive device

101

});

102

103

transport.on("responsive", () => {

104

console.log("Device is responding again");

105

// Hide unresponsive warning

106

});

107

108

// Start a potentially slow operation

109

const signature = await transport.send(0xE0, 0x04, 0x01, 0x00, largeTransaction);

110

```

111

112

### Debug Mode (Deprecated)

113

114

Legacy method for enabling debug logging. This method is deprecated and no longer emits logs.

115

116

```typescript { .api }

117

/**

118

* Enable or not logs of the binary exchange

119

* @deprecated Use @ledgerhq/logs instead. No logs are emitted in this anymore.

120

*/

121

setDebugMode(): void;

122

```

123

124

**Migration Example:**

125

126

```javascript

127

// Old approach (deprecated)

128

transport.setDebugMode();

129

130

// New approach - use @ledgerhq/logs

131

import { setDebugMode } from "@ledgerhq/logs";

132

setDebugMode(true);

133

```

134

135

## Configuration Properties

136

137

### Default Timeout Values

138

139

The Transport class provides default timeout configurations:

140

141

```javascript { .api }

142

class Transport<Descriptor> {

143

/** Default timeout for APDU exchanges (30 seconds) */

144

exchangeTimeout: number = 30000;

145

146

/** Default timeout for unresponsive detection (15 seconds) */

147

unresponsiveTimeout: number = 15000;

148

149

/** Connected device model information */

150

deviceModel: DeviceModel | null = null;

151

152

/** Internal lock to prevent concurrent app API operations */

153

_appAPIlock: string | null = null;

154

155

/** Promise tracking current exchange operation for race condition prevention */

156

exchangeBusyPromise: Promise<void> | null = null;

157

}

158

```

159

160

### Accessing Configuration

161

162

```javascript

163

const transport = await MyTransport.create();

164

165

console.log("Current exchange timeout:", transport.exchangeTimeout);

166

console.log("Current unresponsive timeout:", transport.unresponsiveTimeout);

167

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

168

169

// Modify timeouts

170

transport.setExchangeTimeout(60000); // 1 minute

171

transport.setExchangeUnresponsiveTimeout(10000); // 10 seconds

172

173

console.log("New exchange timeout:", transport.exchangeTimeout);

174

```

175

176

## Security Considerations

177

178

### Scramble Key Best Practices

179

180

1. **App-Specific Keys**: Always use the appropriate scramble key for the target application

181

2. **Key Management**: Store scramble keys securely and don't hardcode them in public repositories

182

3. **Key Rotation**: Some applications may require different keys for different operations

183

184

```javascript

185

// Example: Context-aware scramble key usage

186

class LedgerWalletManager {

187

constructor(transport) {

188

this.transport = transport;

189

}

190

191

async switchToApp(appName) {

192

const scrambleKeys = {

193

'bitcoin': 'BTC',

194

'ethereum': 'ETH',

195

'ripple': 'XRP'

196

};

197

198

const key = scrambleKeys[appName];

199

if (!key) {

200

throw new Error(`Unknown app: ${appName}`);

201

}

202

203

this.transport.setScrambleKey(key);

204

return this.waitForApp(appName);

205

}

206

}

207

```

208

209

### Timeout Configuration Guidelines

210

211

1. **Exchange Timeout**: Set based on expected operation complexity

212

- Simple queries: 5-10 seconds

213

- Transaction signing: 30-60 seconds

214

- Firmware operations: 2-5 minutes

215

216

2. **Unresponsive Timeout**: Balance user experience with false positives

217

- Interactive operations: 5-10 seconds

218

- Background operations: 15-30 seconds

219

220

```javascript

221

// Example: Operation-specific timeout configuration

222

async function performComplexOperation(transport, operationType) {

223

const timeouts = {

224

'quick_query': { exchange: 5000, unresponsive: 3000 },

225

'transaction_sign': { exchange: 30000, unresponsive: 10000 },

226

'firmware_update': { exchange: 300000, unresponsive: 60000 }

227

};

228

229

const config = timeouts[operationType];

230

if (config) {

231

transport.setExchangeTimeout(config.exchange);

232

transport.setExchangeUnresponsiveTimeout(config.unresponsive);

233

}

234

235

// Perform the operation...

236

}

237

```

238

239

## Environment-Specific Configuration

240

241

Different transport implementations may handle configuration differently:

242

243

```javascript

244

// WebUSB transport - timeout affects browser API calls

245

import TransportWebUSB from "@ledgerhq/hw-transport-webusb";

246

const webTransport = await TransportWebUSB.create();

247

webTransport.setExchangeTimeout(15000); // Browser timeout

248

249

// Node.js HID transport - timeout affects system calls

250

import TransportNodeHid from "@ledgerhq/hw-transport-node-hid";

251

const hidTransport = await TransportNodeHid.create();

252

hidTransport.setExchangeTimeout(10000); // System timeout

253

```

254

255

## App API Decoration Methods

256

257

### Batch Method Decoration

258

259

Decorates multiple methods on an object with app API locking and scramble key management.

260

261

```javascript { .api }

262

/**

263

* Decorates multiple methods on an object with app API locking and scramble key management

264

* @param self The object containing methods to decorate

265

* @param methods Array of method names to decorate

266

* @param scrambleKey The scramble key to use for these methods

267

*/

268

decorateAppAPIMethods(

269

self: Object,

270

methods: Array<string>,

271

scrambleKey: string

272

): void;

273

```

274

275

### Single Method Decoration

276

277

Decorates a single method with app API locking and scramble key management.

278

279

```javascript { .api }

280

/**

281

* Decorates a single method with app API locking and scramble key management

282

* @param methodName Name of the method for error reporting

283

* @param f The function to decorate

284

* @param ctx The context (this) to bind the function to

285

* @param scrambleKey The scramble key to use for this method

286

* @returns Decorated function with locking and scramble key management

287

*/

288

decorateAppAPIMethod<R, A: any[]>(

289

methodName: string,

290

f: (...args: A) => Promise<R>,

291

ctx: any,

292

scrambleKey: string

293

): (...args: A) => Promise<R>;

294

```

295

296

**Usage Example:**

297

298

```javascript

299

import Transport from "@ledgerhq/hw-transport";

300

301

class MyLedgerApp {

302

constructor(transport) {

303

this.transport = transport;

304

305

// Decorate multiple methods at once

306

this.transport.decorateAppAPIMethods(

307

this,

308

['getVersion', 'getPublicKey', 'signTransaction'],

309

'BTC'

310

);

311

312

// Or decorate individual methods

313

this.getAddress = this.transport.decorateAppAPIMethod(

314

'getAddress',

315

this._getRawAddress.bind(this),

316

this,

317

'BTC'

318

);

319

}

320

321

// These methods will be automatically decorated with locking

322

async getVersion() {

323

return await this.transport.send(0xB0, 0x01, 0x00, 0x00);

324

}

325

326

async getPublicKey(path) {

327

return await this.transport.send(0xE0, 0x40, 0x00, 0x00, path);

328

}

329

330

async signTransaction(txData) {

331

return await this.transport.send(0xE0, 0x44, 0x00, 0x00, txData);

332

}

333

334

// Raw method that gets decorated

335

async _getRawAddress(path, display) {

336

return await this.transport.send(0xE0, 0x42, display ? 0x01 : 0x00, 0x00, path);

337

}

338

}

339

```

340

341

### App API Lock Property

342

343

The transport maintains an internal lock to prevent concurrent app API operations.

344

345

```javascript { .api }

346

class Transport<Descriptor> {

347

/** Internal lock to prevent concurrent app API operations */

348

_appAPIlock: string | null = null;

349

}

350

```

351

352

When methods are decorated, they automatically:

353

1. Check if another operation is in progress (`_appAPIlock`)

354

2. Set the lock with the method name

355

3. Set the appropriate scramble key

356

4. Execute the method

357

5. Clear the lock when complete

358

359

This prevents race conditions and ensures proper scramble key isolation between different app operations.