@onekeyfe/hwk-ledger-adapter 1.1.27-alpha.34 → 1.1.27-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,30 +1,106 @@
1
- import { IHardwareWallet, IConnector, TransportType, UiResponseEvent, DeviceInfo, Response, ChainCapability, EvmGetAddressParams, EvmAddress, EvmSignTxParams, EvmSignedTx, EvmSignMsgParams, EvmSignature, EvmSignTypedDataParams, BtcGetAddressParams, BtcAddress, BtcGetPublicKeyParams, BtcPublicKey, BtcSignTxParams, BtcSignedTx, BtcSignPsbtParams, BtcSignedPsbt, BtcSignMsgParams, BtcSignature, SolGetAddressParams, SolAddress, SolSignTxParams, SolSignedTx, SolSignMsgParams, SolSignature, TronGetAddressParams, TronAddress, TronSignTxParams, TronSignedTx, TronSignMsgParams, TronSignature, HardwareEventMap, DeviceEventListener, ChainForFingerprint, DeviceDescriptor, DeviceChangeEvent, ConnectionType, ConnectorDevice, ConnectorSession, ConnectorEventType, ConnectorEventMap, Failure, HardwareErrorCode } from '@onekeyfe/hwk-adapter-core';
1
+ import { IHardwareWallet, IConnector, TransportType, UiResponseEvent, SearchDevicesOptions, DeviceInfo, Response, ChainCapability, EvmGetAddressParams, EvmAddress, EvmSignTxParams, EvmSignedTx, EvmSignMsgParams, EvmSignature, EvmSignTypedDataParams, BtcGetAddressParams, BtcAddress, BtcGetPublicKeyParams, BtcPublicKey, BtcSignTxParams, BtcSignedTx, BtcSignPsbtParams, BtcSignedPsbt, BtcSignMsgParams, BtcSignature, SolGetAddressParams, SolAddress, SolSignTxParams, SolSignedTx, SolSignMsgParams, SolSignature, TronGetAddressParams, TronAddress, TronSignTxParams, TronSignedTx, TronSignMsgParams, TronSignature, HardwareEventMap, DeviceEventListener, ChainForFingerprint, DeviceDescriptor, DeviceChangeEvent, ConnectionType, ConnectorDevice, ConnectorSession, ConnectorEventType, ConnectorEventMap, Failure, HardwareErrorCode } from '@onekeyfe/hwk-adapter-core';
2
2
  import { DeviceActionState as DeviceActionState$1, DiscoveredDevice, ExecuteDeviceActionReturnType, DeviceManagementKit } from '@ledgerhq/device-management-kit';
3
3
  import { Address, Signature, SignerEth as SignerEth$1, TypedData } from '@ledgerhq/device-signer-kit-ethereum';
4
+ import { ContextModule } from '@ledgerhq/context-module';
4
5
  import { SignerBtc as SignerBtc$1 } from '@ledgerhq/device-signer-kit-bitcoin';
5
6
  import { SignerSolana } from '@ledgerhq/device-signer-kit-solana';
6
7
  import Transport from '@ledgerhq/hw-transport';
7
8
 
8
- interface LedgerAdapterOptions {
9
- /**
10
- * `true` emit `REQUEST_SELECT_DEVICE` on multi-device discovery and await
11
- * `uiResponse({ type: RECEIVE_SELECT_DEVICE, payload: { sdkConnectId } })`.
12
- * `false` (default) — silently pick the first device.
13
- */
14
- handleSelectDevice?: boolean;
9
+ /**
10
+ * Re-export DMK types under local aliases for backward compatibility.
11
+ * These replace the previous duck-typed interfaces with the real SDK types.
12
+ */
13
+ type DmkDiscoveredDevice = DiscoveredDevice;
14
+ /**
15
+ * DMK DeviceAction — the Observable-based return type of all DMK signer methods.
16
+ *
17
+ * This is a permissive alias for `ExecuteDeviceActionReturnType` that accepts
18
+ * any Error and IntermediateValue generics. Signer wrapper code only cares about
19
+ * the Output type and the observable/cancel shape.
20
+ */
21
+ type DeviceAction<T> = ExecuteDeviceActionReturnType<T, any, any>;
22
+ /**
23
+ * DMK DeviceActionState — re-exported with permissive Error/IntermediateValue.
24
+ * The real type is a discriminated union on `status`.
25
+ */
26
+ type DeviceActionState<T> = DeviceActionState$1<T, any, any>;
27
+ /** ETH address result — re-exported from DMK for backward compatibility. */
28
+ type SignerEvmAddress = Address;
29
+ /** ETH signature result — re-exported from DMK for backward compatibility. */
30
+ type SignerEvmSignature = Signature;
31
+ /** BTC address result (WalletAddress not exported from DMK top-level). */
32
+ interface SignerBtcAddress {
33
+ address: string;
34
+ }
35
+
36
+ /** Optional context attached to the rejection when a canceller fires. */
37
+ interface CancelReason {
38
+ code?: number;
39
+ tag?: string;
40
+ message?: string;
15
41
  }
42
+ /**
43
+ * Convert a DMK DeviceAction (Observable-based) into a Promise.
44
+ * Handles pending -> completed/error state transitions and interaction callbacks.
45
+ *
46
+ * Tracks the last DMK step observed (e.g. `signer.eth.steps.blindSignTransactionFallback`)
47
+ * and attaches it to the rejected error as a non-enumerable `_lastStep` property,
48
+ * so upstream error classifiers can distinguish failure contexts (e.g. Blind signing
49
+ * disabled vs. generic Invalid data).
50
+ *
51
+ * @param timeoutMs Idle watchdog ms. Re-armed on each emission, paused
52
+ * during interactive pending. 0 disables. Default 65s
53
+ * (covers DMK's 60s + margin; we're a backstop only).
54
+ * @param onRegisterCanceller Optional callback that receives a function which, when
55
+ * called, unsubscribes and cancels the underlying DeviceAction
56
+ * (releases DMK's IntentQueue slot). Caller is responsible
57
+ * for invoking the canceller on timeout/abort scenarios.
58
+ */
59
+ declare function deviceActionToPromise<T>(action: DeviceAction<T>, onInteraction?: (interaction: string) => void, timeoutMs?: number, onRegisterCanceller?: (cancel: (reason?: CancelReason) => void) => void, onIntermediate?: (intermediateValue: unknown) => void): Promise<T>;
60
+
61
+ interface AppMetadata {
62
+ versionName: string;
63
+ versionId: number;
64
+ version: string;
65
+ versionDisplayName: string | null;
66
+ description: string | null;
67
+ icon: string | null;
68
+ bytes: number | null;
69
+ currencyId: string | null;
70
+ isDevTools: boolean;
71
+ }
72
+ interface FirmwareVersion {
73
+ /** BOLOS version on the secure element — the user-facing firmware version. */
74
+ seVersion: string;
75
+ /** MCU SEPH (SE–MCU link protocol) version. */
76
+ mcuSephVersion: string;
77
+ /** MCU bootloader version. */
78
+ mcuBootloaderVersion: string;
79
+ /** Hardware revision (e.g. "00" / "01" on Nano X). */
80
+ hwVersion: string;
81
+ }
82
+ /** Full GetOsVersionResponse projected to a plain serializable shape. */
83
+ interface LedgerDeviceInfo extends FirmwareVersion {
84
+ isBootloader: boolean;
85
+ isOsu: boolean;
86
+ targetId: number;
87
+ seTargetId?: number;
88
+ mcuTargetId?: number;
89
+ /** Secure element flags as hex string (raw bytes turned readable). */
90
+ seFlagsHex: string;
91
+ }
92
+
16
93
  declare class LedgerAdapter implements IHardwareWallet {
17
94
  readonly vendor: "ledger";
18
95
  private readonly connector;
19
96
  private readonly emitter;
20
- private readonly _handleSelectDevice;
21
97
  private _discoveredDevices;
22
98
  private _sessions;
23
99
  private readonly _uiRegistry;
24
100
  private _btcHighIndexConfirmedThisSession;
25
101
  private readonly _jobQueue;
26
102
  private _doConnectAbortController;
27
- constructor(connector: IConnector, options?: LedgerAdapterOptions);
103
+ constructor(connector: IConnector);
28
104
  get activeTransport(): TransportType | null;
29
105
  getAvailableTransports(): TransportType[];
30
106
  switchTransport(_type: TransportType): Promise<void>;
@@ -37,8 +113,10 @@ declare class LedgerAdapter implements IHardwareWallet {
37
113
  resetState(): void;
38
114
  dispose(): Promise<void>;
39
115
  uiResponse(response: UiResponseEvent): void;
40
- searchDevices(): Promise<DeviceInfo[]>;
116
+ searchDevices(options?: SearchDevicesOptions): Promise<DeviceInfo[]>;
117
+ private _evictAllSessions;
41
118
  private static readonly MAX_BUSINESS_RETRY_BUDGET;
119
+ private static readonly STUCK_APP_RETRY_DELAY_MS;
42
120
  private static readonly MAX_DOCONNECT_CONFIRMS;
43
121
  private _lastCancelReason;
44
122
  private static _createDeviceBusyError;
@@ -65,6 +143,11 @@ declare class LedgerAdapter implements IHardwareWallet {
65
143
  tronGetAddress(connectId: string, deviceId: string, params: TronGetAddressParams): Promise<Response<TronAddress>>;
66
144
  tronSignTransaction(connectId: string, deviceId: string, params: TronSignTxParams): Promise<Response<TronSignedTx>>;
67
145
  tronSignMessage(connectId: string, deviceId: string, params: TronSignMsgParams): Promise<Response<TronSignature>>;
146
+ installApp(connectId: string, appName: string): Promise<Response<void>>;
147
+ listInstalledApps(connectId: string): Promise<Response<AppMetadata[]>>;
148
+ listAvailableApps(connectId: string): Promise<Response<AppMetadata[]>>;
149
+ getLedgerFirmwareVersion(connectId: string): Promise<Response<FirmwareVersion>>;
150
+ getLedgerDeviceInfo(connectId: string): Promise<Response<LedgerDeviceInfo>>;
68
151
  on<K extends keyof HardwareEventMap>(event: K, listener: (event: HardwareEventMap[K]) => void): void;
69
152
  on(event: string, listener: DeviceEventListener): void;
70
153
  off<K extends keyof HardwareEventMap>(event: K, listener: (event: HardwareEventMap[K]) => void): void;
@@ -96,7 +179,7 @@ declare class LedgerAdapter implements IHardwareWallet {
96
179
  *
97
180
  * - If a session already exists for the given connectId, reuse it.
98
181
  * - If ANY session exists (Ledger IDs are ephemeral), reuse it.
99
- * - Otherwise: search → 1 device: auto-connect, multiple: ask user, 0: throw.
182
+ * - Otherwise: search → exactly 1 USB device auto-connects; multiple or none throws.
100
183
  */
101
184
  private _connectingPromise;
102
185
  private _waitForDeviceConnect;
@@ -113,7 +196,6 @@ declare class LedgerAdapter implements IHardwareWallet {
113
196
  private _doConnect;
114
197
  private _connectFirstOrSelect;
115
198
  private _connectDeviceOrThrow;
116
- private _chooseDeviceFromList;
117
199
  /**
118
200
  * Call the connector with automatic session resolution and disconnect retry.
119
201
  *
@@ -132,6 +214,16 @@ declare class LedgerAdapter implements IHardwareWallet {
132
214
  private static _throwIfAborted;
133
215
  /** Actual work done under the job queue — connection, fingerprint, call, and recovery. */
134
216
  private _runConnectorCall;
217
+ /**
218
+ * Stuck-app recovery: pause for the device's UI transition, then retry once.
219
+ *
220
+ * Caller has already cleared the session + reset connector. We wait so Stax
221
+ * finishes its post-CloseApp animation, then go through ensureConnected +
222
+ * fingerprint check + call exactly once. Caller decides what to do on a
223
+ * second stuck-app hit.
224
+ */
225
+ private _retryAfterStuckApp;
226
+ private _sleepAbortable;
135
227
  /**
136
228
  * Clear stale session, reconnect, and retry the call.
137
229
  *
@@ -161,38 +253,12 @@ declare class LedgerAdapter implements IHardwareWallet {
161
253
  private deviceConnectHandler;
162
254
  private deviceDisconnectHandler;
163
255
  private uiEventForwarder;
256
+ private appInstallProgressForwarder;
164
257
  private registerEventListeners;
165
258
  private unregisterEventListeners;
166
259
  private connectorDeviceToDeviceInfo;
167
260
  }
168
261
 
169
- /**
170
- * Re-export DMK types under local aliases for backward compatibility.
171
- * These replace the previous duck-typed interfaces with the real SDK types.
172
- */
173
- type DmkDiscoveredDevice = DiscoveredDevice;
174
- /**
175
- * DMK DeviceAction — the Observable-based return type of all DMK signer methods.
176
- *
177
- * This is a permissive alias for `ExecuteDeviceActionReturnType` that accepts
178
- * any Error and IntermediateValue generics. Signer wrapper code only cares about
179
- * the Output type and the observable/cancel shape.
180
- */
181
- type DeviceAction<T> = ExecuteDeviceActionReturnType<T, any, any>;
182
- /**
183
- * DMK DeviceActionState — re-exported with permissive Error/IntermediateValue.
184
- * The real type is a discriminated union on `status`.
185
- */
186
- type DeviceActionState<T> = DeviceActionState$1<T, any, any>;
187
- /** ETH address result — re-exported from DMK for backward compatibility. */
188
- type SignerEvmAddress = Address;
189
- /** ETH signature result — re-exported from DMK for backward compatibility. */
190
- type SignerEvmSignature = Signature;
191
- /** BTC address result (WalletAddress not exported from DMK top-level). */
192
- interface SignerBtcAddress {
193
- address: string;
194
- }
195
-
196
262
  /**
197
263
  * Manages device discovery, connection, and session tracking.
198
264
  * Wraps DMK's Observable APIs into simpler imperative calls.
@@ -244,6 +310,14 @@ declare class LedgerDeviceManager {
244
310
  requestDevice(): Promise<void>;
245
311
  /** Lookup a previously-discovered device's display name. */
246
312
  getDeviceName(deviceId: string): string | undefined;
313
+ /** Lookup minimal model/signal info from a previously-discovered device. */
314
+ getDiscoveredDeviceInfo(deviceId: string): {
315
+ model?: string;
316
+ modelName?: string;
317
+ name?: string;
318
+ rssi?: number | null;
319
+ } | undefined;
320
+ hasDiscoveredDevice(deviceId: string): boolean;
247
321
  /** Connect to a previously discovered device. Returns sessionId. */
248
322
  connect(deviceId: string): Promise<string>;
249
323
  /** Disconnect a session. */
@@ -288,22 +362,24 @@ interface LedgerConnectorBaseOptions {
288
362
  * Subclasses only need to:
289
363
  * 1. Supply a transport factory via the constructor.
290
364
  * 2. Optionally override `_resolveConnectId()` for transport-specific
291
- * device identity resolution (e.g. BLE hex ID extraction).
365
+ * device identity resolution.
366
+ *
367
+ * Invariant: one instance = one transport. `connectionType` is fixed at
368
+ * construction. To switch transport (e.g. desktop BLE ↔ WebHID), the host
369
+ * must build a new connector instance and replace the old one — don't add
370
+ * multiple transports to a single instance. Lifting this constraint would
371
+ * require routing `connectionType` from `descriptor.transport` per-device
372
+ * and updating every `this.connectionType` branch in this file.
292
373
  */
293
374
  declare class LedgerConnectorBase implements IConnector {
294
375
  private _deviceManager;
295
376
  private _signerManager;
377
+ private _deviceAppsManager;
296
378
  private _dmk;
297
379
  private readonly _eventHandlers;
298
380
  private readonly _providedDmk;
299
381
  private readonly _createTransport;
300
382
  readonly connectionType: ConnectionType;
301
- private _connectIdToPath;
302
- private _pathToConnectId;
303
- /** Get DMK path from external connectId. Falls back to connectId itself. */
304
- private _getPathForConnectId;
305
- /** Get external connectId from DMK path. Falls back to path itself. */
306
- private _getConnectIdForPath;
307
383
  private readonly _cancellers;
308
384
  private readonly _sessionStateSubs;
309
385
  /**
@@ -314,6 +390,10 @@ declare class LedgerConnectorBase implements IConnector {
314
390
  protected _importLedgerKit: (pkg: string) => Promise<any>;
315
391
  /** Context object passed to per-chain handler functions. */
316
392
  private readonly _ctx;
393
+ /** When true, BLE direct-connect throws NotAdvertising if the pre-flight
394
+ * scan can't see the device — guard for GATT stacks that wedge on
395
+ * non-advertising peripherals (iOS). */
396
+ private readonly _requirePreFlightScan;
317
397
  constructor(createTransport: TransportFactory, options?: {
318
398
  connectionType?: ConnectionType;
319
399
  dmk?: DeviceManagementKit;
@@ -323,11 +403,13 @@ declare class LedgerConnectorBase implements IConnector {
323
403
  * For Metro (React Native): pass a resolver that uses CJS paths.
324
404
  */
325
405
  importLedgerKit?: (pkg: string) => Promise<any>;
406
+ /** Default false. RN-iOS subclass should pass `true`. */
407
+ requirePreFlightScan?: boolean;
326
408
  });
327
409
  /**
328
410
  * Resolve the connectId for a discovered device descriptor.
329
411
  * Default: use the DMK path (ephemeral UUID).
330
- * Override in subclasses to extract stable identifiers (e.g. BLE hex ID).
412
+ * Override in subclasses only when the public connectId differs from the transport path.
331
413
  */
332
414
  protected _resolveConnectId(descriptor: DeviceDescriptor): string;
333
415
  /**
@@ -346,8 +428,7 @@ declare class LedgerConnectorBase implements IConnector {
346
428
  * `LedgerAdapter._sessions` map would hold a dead session entry until
347
429
  * the next call hit `DeviceSessionNotFound`.
348
430
  *
349
- * Best-effort: any error subscribing is swallowed so a flaky DMK
350
- * doesn't break the connect path.
431
+ * Subscribe failure is fatal see the inline note at the subscribe call.
351
432
  */
352
433
  private _watchSessionState;
353
434
  private _unwatchSessionState;
@@ -368,15 +449,15 @@ declare class LedgerConnectorBase implements IConnector {
368
449
  private _initManagers;
369
450
  private _getDeviceManager;
370
451
  private _getSignerManager;
452
+ private _getDeviceAppsManager;
371
453
  private _invalidateSession;
372
454
  /**
373
455
  * Replace an old session with a new one after app switch.
374
- * Updates the connectId→path mapping so subsequent calls() use the new session,
375
- * and emits device-connect so the adapter updates its _sessions Map.
456
+ * Emits device-connect so the adapter updates its _sessions Map.
376
457
  */
377
458
  private _replaceSession;
378
459
  /**
379
- * Light reset: clear signer/session state but keep DMK and ID mapping alive.
460
+ * Light reset: clear signer/session state but keep DMK alive.
380
461
  * Used by connect() retry — we want to re-discover with the same transport.
381
462
  *
382
463
  * Note: drops the device manager but tears down its RxJS subs first via
@@ -395,31 +476,6 @@ declare class LedgerConnectorBase implements IConnector {
395
476
  private _wrapError;
396
477
  }
397
478
 
398
- /** Optional context attached to the rejection when a canceller fires. */
399
- interface CancelReason {
400
- code?: number;
401
- tag?: string;
402
- message?: string;
403
- }
404
- /**
405
- * Convert a DMK DeviceAction (Observable-based) into a Promise.
406
- * Handles pending -> completed/error state transitions and interaction callbacks.
407
- *
408
- * Tracks the last DMK step observed (e.g. `signer.eth.steps.blindSignTransactionFallback`)
409
- * and attaches it to the rejected error as a non-enumerable `_lastStep` property,
410
- * so upstream error classifiers can distinguish failure contexts (e.g. Blind signing
411
- * disabled vs. generic Invalid data).
412
- *
413
- * @param timeoutMs Idle watchdog ms. Re-armed on each emission, paused
414
- * during interactive pending. 0 disables. Default 65s
415
- * (covers DMK's 60s + margin; we're a backstop only).
416
- * @param onRegisterCanceller Optional callback that receives a function which, when
417
- * called, unsubscribes and cancels the underlying DeviceAction
418
- * (releases DMK's IntentQueue slot). Caller is responsible
419
- * for invoking the canceller on timeout/abort scenarios.
420
- */
421
- declare function deviceActionToPromise<T>(action: DeviceAction<T>, onInteraction?: (interaction: string) => void, timeoutMs?: number, onRegisterCanceller?: (cancel: (reason?: CancelReason) => void) => void): Promise<T>;
422
-
423
479
  /**
424
480
  * Wraps Ledger's SDK signer (Observable-based DeviceActions) into
425
481
  * a simple async interface returning plain serializable data.
@@ -446,8 +502,14 @@ type SignerEthBuilderFn = (args: {
446
502
  dmk: DeviceManagementKit;
447
503
  sessionId: string;
448
504
  }) => {
505
+ withContextModule?(contextModule: ContextModule): {
506
+ build(): SignerEth$1;
507
+ };
449
508
  build(): SignerEth$1;
450
509
  } | Promise<{
510
+ withContextModule?(contextModule: ContextModule): {
511
+ build(): SignerEth$1;
512
+ };
451
513
  build(): SignerEth$1;
452
514
  }>;
453
515
  /**
@@ -463,6 +525,8 @@ declare class SignerManager {
463
525
  invalidate(_sessionId: string): void;
464
526
  clearAll(): void;
465
527
  private static _defaultBuilder;
528
+ private static _createContextModule;
529
+ static wrapBlindSigningReportNonBlocking<T extends ContextModule>(contextModule: T): T;
466
530
  }
467
531
 
468
532
  type BtcWallet = Parameters<SignerBtc$1['getWalletAddress']>[0];
@@ -655,12 +719,7 @@ type SdkEventListener = (event: SdkEvent) => void;
655
719
  declare function onSdkEvent(listener: SdkEventListener): () => void;
656
720
  declare function offSdkEvent(listener: SdkEventListener): void;
657
721
 
658
- /**
659
- * Extract the stable 4-digit HEX identifier from a Ledger BLE device name.
660
- * e.g., "Nano X 123A" -> "123A", "Ledger Nano X AB12" -> "AB12"
661
- * Returns undefined if no valid HEX suffix found.
662
- */
663
- declare function extractBleHexId(name?: string): string | undefined;
722
+ declare function debugLog(...args: unknown[]): void;
664
723
 
665
724
  /**
666
725
  * Ledger DMK transport identifiers that represent BLE devices.
@@ -675,6 +734,5 @@ declare function extractBleHexId(name?: string): string | undefined;
675
734
  declare function isLedgerDmkBleTransport(transport?: string): boolean;
676
735
  declare function isLedgerBleConnectionType(connectionType?: ConnectionType): boolean;
677
736
  declare function isLedgerBleDescriptor(connectionType: ConnectionType, descriptor: DeviceDescriptor): boolean;
678
- declare function isValidLedgerBleConnectId(connectId?: string): boolean;
679
737
 
680
- export { AppManager, type DeviceActionState, type DmkDiscoveredDevice, DmkTransport, LedgerAdapter, LedgerConnectorBase, type LedgerConnectorBaseOptions, LedgerDeviceManager, type LedgerFailure, type SdkEvent, type SdkEventListener, type SdkLogEvent, SignerBtc, type SignerBtcAddress, SignerEth, type SignerEvmAddress, type SignerEvmSignature, SignerManager, SignerSol, type TransportFactory, deviceActionToPromise, extractBleHexId, isDeviceLockedError, isLedgerBleConnectionType, isLedgerBleDescriptor, isLedgerDmkBleTransport, isValidLedgerBleConnectId, ledgerFailure, mapLedgerError, offSdkEvent, onSdkEvent };
738
+ export { AppManager, type DeviceActionState, type DmkDiscoveredDevice, DmkTransport, LedgerAdapter, LedgerConnectorBase, type LedgerConnectorBaseOptions, LedgerDeviceManager, type LedgerFailure, type SdkEvent, type SdkEventListener, type SdkLogEvent, SignerBtc, type SignerBtcAddress, SignerEth, type SignerEvmAddress, type SignerEvmSignature, SignerManager, SignerSol, type TransportFactory, debugLog, deviceActionToPromise, isDeviceLockedError, isLedgerBleConnectionType, isLedgerBleDescriptor, isLedgerDmkBleTransport, ledgerFailure, mapLedgerError, offSdkEvent, onSdkEvent };