@onekeyfe/hwk-ledger-adapter 1.1.26-alpha.9 → 1.1.26-patch.1

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.ts CHANGED
@@ -1,45 +1,22 @@
1
- import { IHardwareWallet, IConnector, TransportType, UiResponseEvent, DeviceInfo, Response, ChainCapability, EvmGetAddressParams, EvmAddress, ProgressCallback, 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, ConnectionType, DeviceDescriptor, ConnectorDevice, ConnectorSession, ConnectorEventType, ConnectorEventMap, DeviceChangeEvent, Failure, HardwareErrorCode } from '@onekeyfe/hwk-adapter-core';
2
- import { DeviceManagementKit, DeviceActionState as DeviceActionState$1, DiscoveredDevice, ExecuteDeviceActionReturnType } from '@ledgerhq/device-management-kit';
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
+ 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;
15
- }
16
- /**
17
- * Ledger hardware wallet adapter that delegates to an IConnector.
18
- *
19
- * This is a thin translation layer that:
20
- * - Accepts a pre-configured IConnector (transport decisions are made at connector creation time)
21
- * - Translates IHardwareWallet method calls to connector.call() invocations
22
- * - Maps connector results/errors to our Response<T> format with enriched error messages
23
- * - Translates connector events to HardwareEventMap events
24
- * - Emits `REQUEST_DEVICE_PERMISSION` for OS-level permission checks
25
- */
26
9
  declare class LedgerAdapter implements IHardwareWallet {
27
10
  readonly vendor: "ledger";
28
11
  private readonly connector;
29
12
  private readonly emitter;
30
- private readonly _handleSelectDevice;
31
13
  private _discoveredDevices;
32
14
  private _sessions;
33
15
  private readonly _uiRegistry;
16
+ private _btcHighIndexConfirmedThisSession;
34
17
  private readonly _jobQueue;
35
- constructor(connector: IConnector, options?: LedgerAdapterOptions);
36
- /**
37
- * Classify a method's interruptibility.
38
- * - Signing / typed data / transaction → 'confirm' (user may decide via preemption UI)
39
- * - Read-only queries (getAddress / getPublicKey / getMasterFingerprint) → 'safe'
40
- * (auto-cancels any pending read for the same device)
41
- */
42
- private static _getInterruptibility;
18
+ private _doConnectAbortController;
19
+ constructor(connector: IConnector);
43
20
  get activeTransport(): TransportType | null;
44
21
  getAvailableTransports(): TransportType[];
45
22
  switchTransport(_type: TransportType): Promise<void>;
@@ -52,24 +29,23 @@ declare class LedgerAdapter implements IHardwareWallet {
52
29
  resetState(): void;
53
30
  dispose(): Promise<void>;
54
31
  uiResponse(response: UiResponseEvent): void;
55
- searchDevices(): Promise<DeviceInfo[]>;
32
+ searchDevices(options?: SearchDevicesOptions): Promise<DeviceInfo[]>;
33
+ private _evictAllSessions;
34
+ private static readonly MAX_BUSINESS_RETRY_BUDGET;
35
+ private static readonly STUCK_APP_RETRY_DELAY_MS;
36
+ private static readonly MAX_DOCONNECT_CONFIRMS;
37
+ private _lastCancelReason;
38
+ private static _createDeviceBusyError;
56
39
  connectDevice(connectId: string): Promise<Response<string>>;
57
40
  disconnectDevice(connectId: string): Promise<void>;
58
41
  getDeviceInfo(connectId: string, deviceId: string): Promise<Response<DeviceInfo>>;
59
42
  getSupportedChains(): ChainCapability[];
60
43
  private callChain;
61
- /**
62
- * Batch version of callChain — checks permission once,
63
- * fingerprint is verified on the first call inside connectorCall.
64
- */
65
- private callChainBatch;
66
44
  evmGetAddress(connectId: string, deviceId: string, params: EvmGetAddressParams): Promise<Response<EvmAddress>>;
67
- evmGetAddresses(connectId: string, deviceId: string, params: EvmGetAddressParams[], onProgress?: ProgressCallback): Promise<Response<EvmAddress[]>>;
68
45
  evmSignTransaction(connectId: string, deviceId: string, params: EvmSignTxParams): Promise<Response<EvmSignedTx>>;
69
46
  evmSignMessage(connectId: string, deviceId: string, params: EvmSignMsgParams): Promise<Response<EvmSignature>>;
70
47
  evmSignTypedData(connectId: string, deviceId: string, params: EvmSignTypedDataParams): Promise<Response<EvmSignature>>;
71
48
  btcGetAddress(connectId: string, deviceId: string, params: BtcGetAddressParams): Promise<Response<BtcAddress>>;
72
- btcGetAddresses(connectId: string, deviceId: string, params: BtcGetAddressParams[], onProgress?: ProgressCallback): Promise<Response<BtcAddress[]>>;
73
49
  btcGetPublicKey(connectId: string, deviceId: string, params: BtcGetPublicKeyParams): Promise<Response<BtcPublicKey>>;
74
50
  btcSignTransaction(connectId: string, deviceId: string, params: BtcSignTxParams): Promise<Response<BtcSignedTx>>;
75
51
  btcSignPsbt(connectId: string, deviceId: string, params: BtcSignPsbtParams): Promise<Response<BtcSignedPsbt>>;
@@ -78,18 +54,16 @@ declare class LedgerAdapter implements IHardwareWallet {
78
54
  masterFingerprint: string;
79
55
  }>>;
80
56
  solGetAddress(connectId: string, deviceId: string, params: SolGetAddressParams): Promise<Response<SolAddress>>;
81
- solGetAddresses(connectId: string, deviceId: string, params: SolGetAddressParams[], onProgress?: ProgressCallback): Promise<Response<SolAddress[]>>;
82
57
  solSignTransaction(connectId: string, deviceId: string, params: SolSignTxParams): Promise<Response<SolSignedTx>>;
83
58
  solSignMessage(connectId: string, deviceId: string, params: SolSignMsgParams): Promise<Response<SolSignature>>;
84
59
  tronGetAddress(connectId: string, deviceId: string, params: TronGetAddressParams): Promise<Response<TronAddress>>;
85
- tronGetAddresses(connectId: string, deviceId: string, params: TronGetAddressParams[], onProgress?: ProgressCallback): Promise<Response<TronAddress[]>>;
86
60
  tronSignTransaction(connectId: string, deviceId: string, params: TronSignTxParams): Promise<Response<TronSignedTx>>;
87
61
  tronSignMessage(connectId: string, deviceId: string, params: TronSignMsgParams): Promise<Response<TronSignature>>;
88
62
  on<K extends keyof HardwareEventMap>(event: K, listener: (event: HardwareEventMap[K]) => void): void;
89
63
  on(event: string, listener: DeviceEventListener): void;
90
64
  off<K extends keyof HardwareEventMap>(event: K, listener: (event: HardwareEventMap[K]) => void): void;
91
65
  off(event: string, listener: DeviceEventListener): void;
92
- cancel(connectId: string): void;
66
+ cancel(connectId?: string): void;
93
67
  getChainFingerprint(connectId: string, deviceId: string, chain: ChainForFingerprint): Promise<Response<string>>;
94
68
  /**
95
69
  * Verify fingerprint using an existing sessionId directly.
@@ -116,15 +90,23 @@ declare class LedgerAdapter implements IHardwareWallet {
116
90
  *
117
91
  * - If a session already exists for the given connectId, reuse it.
118
92
  * - If ANY session exists (Ledger IDs are ephemeral), reuse it.
119
- * - Otherwise: search → 1 device: auto-connect, multiple: ask user, 0: throw.
93
+ * - Otherwise: search → exactly 1 USB device auto-connects; multiple or none throws.
120
94
  */
121
- private static readonly MAX_DEVICE_RETRY;
122
95
  private _connectingPromise;
123
96
  private _waitForDeviceConnect;
97
+ /**
98
+ * Decide whether a BTC pubkey call needs `showOnDevice=true` because of
99
+ * the BTC App's account-index policy, asking the user once per session.
100
+ *
101
+ * Returns the params to pass through (with `showOnDevice` possibly
102
+ * promoted), or `null` if the user declined.
103
+ */
104
+ private _gateBtcHighIndex;
105
+ private _waitForBtcHighIndexConfirm;
124
106
  private ensureConnected;
125
107
  private _doConnect;
126
108
  private _connectFirstOrSelect;
127
- private _chooseDeviceFromList;
109
+ private _connectDeviceOrThrow;
128
110
  /**
129
111
  * Call the connector with automatic session resolution and disconnect retry.
130
112
  *
@@ -135,16 +117,31 @@ declare class LedgerAdapter implements IHardwareWallet {
135
117
  */
136
118
  private connectorCall;
137
119
  /**
138
- * Race a promise against an abort signal. If the signal fires, rejects with the
139
- * signal's reason (or a generic Error). The underlying connector.call() cannot
140
- * actually be cancelled on Ledger DMK, but the caller gets the abort immediately.
120
+ * Race a promise against an abort signal. On abort, rejects with
121
+ * signal.reason instance _lastCancelReason → generic Error('Aborted').
141
122
  */
142
- private static _abortable;
123
+ private _abortable;
143
124
  /** Throw an AbortError if signal is already aborted. */
144
125
  private static _throwIfAborted;
145
126
  /** Actual work done under the job queue — connection, fingerprint, call, and recovery. */
146
127
  private _runConnectorCall;
147
- /** Clear stale session, reconnect, and retry the call. */
128
+ /**
129
+ * Stuck-app recovery: pause for the device's UI transition, then retry once.
130
+ *
131
+ * Caller has already cleared the session + reset connector. We wait so Stax
132
+ * finishes its post-CloseApp animation, then go through ensureConnected +
133
+ * fingerprint check + call exactly once. Caller decides what to do on a
134
+ * second stuck-app hit.
135
+ */
136
+ private _retryAfterStuckApp;
137
+ private _sleepAbortable;
138
+ /**
139
+ * Clear stale session, reconnect, and retry the call.
140
+ *
141
+ * Timeout recovery starts with a full connector reset. After an APDU
142
+ * timeout, DMK/transport state may still emit malformed responses; retrying
143
+ * on the same DMK can poison the next chain switch.
144
+ */
148
145
  private _retryWithFreshConnection;
149
146
  /**
150
147
  * Ensure OS-level device permission (Bluetooth / USB) before proceeding.
@@ -172,6 +169,111 @@ declare class LedgerAdapter implements IHardwareWallet {
172
169
  private connectorDeviceToDeviceInfo;
173
170
  }
174
171
 
172
+ /**
173
+ * Re-export DMK types under local aliases for backward compatibility.
174
+ * These replace the previous duck-typed interfaces with the real SDK types.
175
+ */
176
+ type DmkDiscoveredDevice = DiscoveredDevice;
177
+ /**
178
+ * DMK DeviceAction — the Observable-based return type of all DMK signer methods.
179
+ *
180
+ * This is a permissive alias for `ExecuteDeviceActionReturnType` that accepts
181
+ * any Error and IntermediateValue generics. Signer wrapper code only cares about
182
+ * the Output type and the observable/cancel shape.
183
+ */
184
+ type DeviceAction<T> = ExecuteDeviceActionReturnType<T, any, any>;
185
+ /**
186
+ * DMK DeviceActionState — re-exported with permissive Error/IntermediateValue.
187
+ * The real type is a discriminated union on `status`.
188
+ */
189
+ type DeviceActionState<T> = DeviceActionState$1<T, any, any>;
190
+ /** ETH address result — re-exported from DMK for backward compatibility. */
191
+ type SignerEvmAddress = Address;
192
+ /** ETH signature result — re-exported from DMK for backward compatibility. */
193
+ type SignerEvmSignature = Signature;
194
+ /** BTC address result (WalletAddress not exported from DMK top-level). */
195
+ interface SignerBtcAddress {
196
+ address: string;
197
+ }
198
+
199
+ /**
200
+ * Manages device discovery, connection, and session tracking.
201
+ * Wraps DMK's Observable APIs into simpler imperative calls.
202
+ */
203
+ declare class LedgerDeviceManager {
204
+ private readonly _dmk;
205
+ private readonly _discovered;
206
+ private readonly _sessions;
207
+ private readonly _sessionToDevice;
208
+ private _listenSub;
209
+ constructor(dmk: DeviceManagementKit);
210
+ /**
211
+ * One-shot enumeration: subscribe to listenToAvailableDevices,
212
+ * take the first emission, unsubscribe, return DeviceDescriptors.
213
+ */
214
+ enumerate(): Promise<DeviceDescriptor[]>;
215
+ /**
216
+ * Continuous listening: tracks device connect/disconnect via diffing.
217
+ */
218
+ listen(onChange: (event: DeviceChangeEvent) => void): void;
219
+ stopListening(): void;
220
+ /**
221
+ * Resolve to the latest snapshot of advertising devices observed within
222
+ * `timeoutMs`. Rewrites `_discovered` so it tracks the live list.
223
+ *
224
+ * `listenToAvailableDevices` is a BehaviorSubject — it emits the cached
225
+ * list on subscribe and *only* re-emits when the list changes. A stable
226
+ * list of currently-advertising devices therefore produces only the
227
+ * subscription frame; treating that frame as "fossil to be discarded"
228
+ * caused devices to flicker in/out of the UI as searches alternated
229
+ * between "saw a change frame" and "saw only the cached frame".
230
+ *
231
+ * The window still gives a chance for the active scan to update the list
232
+ * (e.g. drop a peripheral that just stopped broadcasting), but if nothing
233
+ * changes we trust the snapshot — DMK silence on a stable list means
234
+ * "everything's still there".
235
+ */
236
+ getLiveDevices(timeoutMs?: number): Promise<DmkDiscoveredDevice[]>;
237
+ /**
238
+ * Trigger browser device selection (WebHID requestDevice).
239
+ * Starts discovery for a short period, then stops.
240
+ */
241
+ /**
242
+ * Start BLE discovery if not already running.
243
+ * Does NOT stop — DMK keeps scanning in the background so that
244
+ * listenToAvailableDevices() always has fresh data.
245
+ */
246
+ private _discoverySub;
247
+ requestDevice(): Promise<void>;
248
+ /** Lookup a previously-discovered device's display name. */
249
+ getDeviceName(deviceId: string): string | undefined;
250
+ /** Lookup minimal model/signal info from a previously-discovered device. */
251
+ getDiscoveredDeviceInfo(deviceId: string): {
252
+ model?: string;
253
+ modelName?: string;
254
+ name?: string;
255
+ rssi?: number | null;
256
+ } | undefined;
257
+ hasDiscoveredDevice(deviceId: string): boolean;
258
+ /** Connect to a previously discovered device. Returns sessionId. */
259
+ connect(deviceId: string): Promise<string>;
260
+ /** Disconnect a session. */
261
+ disconnect(sessionId: string): Promise<void>;
262
+ getSessionId(deviceId: string): string | undefined;
263
+ getDeviceId(sessionId: string): string | undefined;
264
+ /** Get the underlying DMK instance (needed by SignerManager). */
265
+ getDmk(): DeviceManagementKit;
266
+ stopDiscovery(): void;
267
+ dispose(): void;
268
+ /**
269
+ * Tear down RxJS subscriptions and local state without closing the DMK.
270
+ * For light-reset paths that want to drop session state but keep the
271
+ * underlying transport alive for retry. Call this instead of orphaning
272
+ * the manager — bare null assignment leaks _listenSub / _discoverySub.
273
+ */
274
+ disposeKeepingDmk(): void;
275
+ }
276
+
175
277
  /**
176
278
  * A function that lazily loads and returns the transport factory
177
279
  * for the Ledger DMK builder (e.g. webHidTransportFactory, rnBleTransportFactory).
@@ -197,7 +299,14 @@ interface LedgerConnectorBaseOptions {
197
299
  * Subclasses only need to:
198
300
  * 1. Supply a transport factory via the constructor.
199
301
  * 2. Optionally override `_resolveConnectId()` for transport-specific
200
- * device identity resolution (e.g. BLE hex ID extraction).
302
+ * device identity resolution.
303
+ *
304
+ * Invariant: one instance = one transport. `connectionType` is fixed at
305
+ * construction. To switch transport (e.g. desktop BLE ↔ WebHID), the host
306
+ * must build a new connector instance and replace the old one — don't add
307
+ * multiple transports to a single instance. Lifting this constraint would
308
+ * require routing `connectionType` from `descriptor.transport` per-device
309
+ * and updating every `this.connectionType` branch in this file.
201
310
  */
202
311
  declare class LedgerConnectorBase implements IConnector {
203
312
  private _deviceManager;
@@ -207,15 +316,8 @@ declare class LedgerConnectorBase implements IConnector {
207
316
  private readonly _providedDmk;
208
317
  private readonly _createTransport;
209
318
  readonly connectionType: ConnectionType;
210
- private _connectIdToPath;
211
- private _pathToConnectId;
212
- /** Register a connectId <-> path mapping from a device descriptor. */
213
- private _registerDeviceId;
214
- /** Get DMK path from external connectId. Falls back to connectId itself. */
215
- private _getPathForConnectId;
216
- /** Get external connectId from DMK path. Falls back to path itself. */
217
- private _getConnectIdForPath;
218
319
  private readonly _cancellers;
320
+ private readonly _sessionStateSubs;
219
321
  /**
220
322
  * Resolves a Ledger signer kit module by package name.
221
323
  * Override via constructor to use CJS paths for Metro (React Native).
@@ -224,6 +326,10 @@ declare class LedgerConnectorBase implements IConnector {
224
326
  protected _importLedgerKit: (pkg: string) => Promise<any>;
225
327
  /** Context object passed to per-chain handler functions. */
226
328
  private readonly _ctx;
329
+ /** When true, BLE direct-connect throws NotAdvertising if the pre-flight
330
+ * scan can't see the device — guard for GATT stacks that wedge on
331
+ * non-advertising peripherals (iOS). */
332
+ private readonly _requirePreFlightScan;
227
333
  constructor(createTransport: TransportFactory, options?: {
228
334
  connectionType?: ConnectionType;
229
335
  dmk?: DeviceManagementKit;
@@ -233,17 +339,39 @@ declare class LedgerConnectorBase implements IConnector {
233
339
  * For Metro (React Native): pass a resolver that uses CJS paths.
234
340
  */
235
341
  importLedgerKit?: (pkg: string) => Promise<any>;
342
+ /** Default false. RN-iOS subclass should pass `true`. */
343
+ requirePreFlightScan?: boolean;
236
344
  });
237
345
  /**
238
346
  * Resolve the connectId for a discovered device descriptor.
239
347
  * Default: use the DMK path (ephemeral UUID).
240
- * Override in subclasses to extract stable identifiers (e.g. BLE hex ID).
348
+ * Override in subclasses only when the public connectId differs from the transport path.
241
349
  */
242
350
  protected _resolveConnectId(descriptor: DeviceDescriptor): string;
351
+ /**
352
+ * Authoritative discovery for this transport. Default = enumerate snapshot
353
+ * (USB/HID). BLE overrides to drive from a live scan window since DMK's
354
+ * enumerate() cache survives peripherals going offline.
355
+ */
356
+ protected _discoverDescriptors(dm: LedgerDeviceManager): Promise<DeviceDescriptor[]>;
357
+ private _assertSingleUsbDescriptor;
243
358
  searchDevices(): Promise<ConnectorDevice[]>;
244
359
  connect(deviceId?: string): Promise<ConnectorSession>;
245
360
  disconnect(sessionId: string): Promise<void>;
361
+ /**
362
+ * Subscribe to DMK's per-session state observable so that any autonomous
363
+ * disconnect (USB unplug, BLE drop, device sleep, transport reset) is
364
+ * surfaced as a `device-disconnect` event — without this, the upstream
365
+ * `LedgerAdapter._sessions` map would hold a dead session entry until
366
+ * the next call hit `DeviceSessionNotFound`.
367
+ *
368
+ * Subscribe failure is fatal — see the inline note at the subscribe call.
369
+ */
370
+ private _watchSessionState;
371
+ private _unwatchSessionState;
372
+ private _handleAutonomousDisconnect;
246
373
  call(sessionId: string, method: string, params: unknown): Promise<unknown>;
374
+ private _dispatch;
247
375
  cancel(sessionId: string): Promise<void>;
248
376
  uiResponse(_response: UiResponseEvent): void;
249
377
  on<K extends ConnectorEventType>(event: K, handler: (data: ConnectorEventMap[K]) => void): void;
@@ -261,13 +389,16 @@ declare class LedgerConnectorBase implements IConnector {
261
389
  private _invalidateSession;
262
390
  /**
263
391
  * Replace an old session with a new one after app switch.
264
- * Updates the connectId→path mapping so subsequent calls() use the new session,
265
- * and emits device-connect so the adapter updates its _sessions Map.
392
+ * Emits device-connect so the adapter updates its _sessions Map.
266
393
  */
267
394
  private _replaceSession;
268
395
  /**
269
- * Light reset: clear signer/session state but keep DMK, BLE scan, and ID mapping alive.
396
+ * Light reset: clear signer/session state but keep DMK alive.
270
397
  * Used by connect() retry — we want to re-discover with the same transport.
398
+ *
399
+ * Note: drops the device manager but tears down its RxJS subs first via
400
+ * disposeKeepingDmk(). Bare null-assignment would leak _listenSub /
401
+ * _discoverySub and double-scan after the next _initManagers().
271
402
  */
272
403
  private _resetSignersAndSessions;
273
404
  private _resetAll;
@@ -281,76 +412,30 @@ declare class LedgerConnectorBase implements IConnector {
281
412
  private _wrapError;
282
413
  }
283
414
 
284
- /**
285
- * Manages device discovery, connection, and session tracking.
286
- * Wraps DMK's Observable APIs into simpler imperative calls.
287
- */
288
- declare class LedgerDeviceManager {
289
- private readonly _dmk;
290
- private readonly _discovered;
291
- private readonly _sessions;
292
- private readonly _sessionToDevice;
293
- private _listenSub;
294
- constructor(dmk: DeviceManagementKit);
295
- /**
296
- * One-shot enumeration: subscribe to listenToAvailableDevices,
297
- * take the first emission, unsubscribe, return DeviceDescriptors.
298
- */
299
- enumerate(): Promise<DeviceDescriptor[]>;
300
- /**
301
- * Continuous listening: tracks device connect/disconnect via diffing.
302
- */
303
- listen(onChange: (event: DeviceChangeEvent) => void): void;
304
- stopListening(): void;
305
- /**
306
- * Trigger browser device selection (WebHID requestDevice).
307
- * Starts discovery for a short period, then stops.
308
- */
309
- /**
310
- * Start BLE discovery if not already running.
311
- * Does NOT stop — DMK keeps scanning in the background so that
312
- * listenToAvailableDevices() always has fresh data.
313
- */
314
- private _discoverySub;
315
- requestDevice(): Promise<void>;
316
- /** Connect to a previously discovered device. Returns sessionId. */
317
- connect(deviceId: string): Promise<string>;
318
- /** Disconnect a session. */
319
- disconnect(sessionId: string): Promise<void>;
320
- getSessionId(deviceId: string): string | undefined;
321
- getDeviceId(sessionId: string): string | undefined;
322
- /** Get the underlying DMK instance (needed by SignerManager). */
323
- getDmk(): DeviceManagementKit;
324
- stopDiscovery(): void;
325
- dispose(): void;
415
+ /** Optional context attached to the rejection when a canceller fires. */
416
+ interface CancelReason {
417
+ code?: number;
418
+ tag?: string;
419
+ message?: string;
326
420
  }
327
-
328
- /**
329
- * Re-export DMK types under local aliases for backward compatibility.
330
- * These replace the previous duck-typed interfaces with the real SDK types.
331
- */
332
- type DmkDiscoveredDevice = DiscoveredDevice;
333
421
  /**
334
- * DMK DeviceAction — the Observable-based return type of all DMK signer methods.
422
+ * Convert a DMK DeviceAction (Observable-based) into a Promise.
423
+ * Handles pending -> completed/error state transitions and interaction callbacks.
335
424
  *
336
- * This is a permissive alias for `ExecuteDeviceActionReturnType` that accepts
337
- * any Error and IntermediateValue generics. Signer wrapper code only cares about
338
- * the Output type and the observable/cancel shape.
339
- */
340
- type DeviceAction<T> = ExecuteDeviceActionReturnType<T, any, any>;
341
- /**
342
- * DMK DeviceActionState re-exported with permissive Error/IntermediateValue.
343
- * The real type is a discriminated union on `status`.
425
+ * Tracks the last DMK step observed (e.g. `signer.eth.steps.blindSignTransactionFallback`)
426
+ * and attaches it to the rejected error as a non-enumerable `_lastStep` property,
427
+ * so upstream error classifiers can distinguish failure contexts (e.g. Blind signing
428
+ * disabled vs. generic Invalid data).
429
+ *
430
+ * @param timeoutMs Idle watchdog ms. Re-armed on each emission, paused
431
+ * during interactive pending. 0 disables. Default 65s
432
+ * (covers DMK's 60s + margin; we're a backstop only).
433
+ * @param onRegisterCanceller Optional callback that receives a function which, when
434
+ * called, unsubscribes and cancels the underlying DeviceAction
435
+ * (releases DMK's IntentQueue slot). Caller is responsible
436
+ * for invoking the canceller on timeout/abort scenarios.
344
437
  */
345
- type DeviceActionState<T> = DeviceActionState$1<T, any, any>;
346
- /** ETH address result — re-exported from DMK for backward compatibility. */
347
- type SignerEvmAddress = Address;
348
- /** ETH signature result — re-exported from DMK for backward compatibility. */
349
- type SignerEvmSignature = Signature;
350
- /** BTC address result (WalletAddress not exported from DMK top-level). */
351
- interface SignerBtcAddress {
352
- address: string;
353
- }
438
+ declare function deviceActionToPromise<T>(action: DeviceAction<T>, onInteraction?: (interaction: string) => void, timeoutMs?: number, onRegisterCanceller?: (cancel: (reason?: CancelReason) => void) => void): Promise<T>;
354
439
 
355
440
  /**
356
441
  * Wraps Ledger's SDK signer (Observable-based DeviceActions) into
@@ -365,7 +450,7 @@ declare class SignerEth {
365
450
  * for the underlying DeviceAction. Caller can invoke it to release DMK's
366
451
  * IntentQueue slot and unsubscribe from the action's observable.
367
452
  */
368
- onRegisterCanceller?: (cancel: () => void) => void;
453
+ onRegisterCanceller?: (cancel: (reason?: CancelReason) => void) => void;
369
454
  getAddress(derivationPath: string, options?: {
370
455
  checkOnDevice?: boolean;
371
456
  }): Promise<SignerEvmAddress>;
@@ -378,8 +463,14 @@ type SignerEthBuilderFn = (args: {
378
463
  dmk: DeviceManagementKit;
379
464
  sessionId: string;
380
465
  }) => {
466
+ withContextModule?(contextModule: ContextModule): {
467
+ build(): SignerEth$1;
468
+ };
381
469
  build(): SignerEth$1;
382
470
  } | Promise<{
471
+ withContextModule?(contextModule: ContextModule): {
472
+ build(): SignerEth$1;
473
+ };
383
474
  build(): SignerEth$1;
384
475
  }>;
385
476
  /**
@@ -395,6 +486,8 @@ declare class SignerManager {
395
486
  invalidate(_sessionId: string): void;
396
487
  clearAll(): void;
397
488
  private static _defaultBuilder;
489
+ private static _createContextModule;
490
+ static wrapBlindSigningReportNonBlocking<T extends ContextModule>(contextModule: T): T;
398
491
  }
399
492
 
400
493
  type BtcWallet = Parameters<SignerBtc$1['getWalletAddress']>[0];
@@ -408,7 +501,7 @@ type BtcMessageOptions = Parameters<SignerBtc$1['signMessage']>[2];
408
501
  declare class SignerBtc {
409
502
  private readonly _sdk;
410
503
  onInteraction?: (interaction: string) => void;
411
- onRegisterCanceller?: (cancel: () => void) => void;
504
+ onRegisterCanceller?: (cancel: (reason?: CancelReason) => void) => void;
412
505
  constructor(_sdk: SignerBtc$1);
413
506
  getWalletAddress(wallet: BtcWallet, addressIndex: number, options?: {
414
507
  checkOnDevice?: boolean;
@@ -454,7 +547,7 @@ type SolMsgOptions = Parameters<SignerSolana['signMessage']>[2];
454
547
  declare class SignerSol {
455
548
  private readonly _sdk;
456
549
  onInteraction?: (interaction: string) => void;
457
- onRegisterCanceller?: (cancel: () => void) => void;
550
+ onRegisterCanceller?: (cancel: (reason?: CancelReason) => void) => void;
458
551
  constructor(_sdk: SignerSolana);
459
552
  /**
460
553
  * Get the Solana address (base58-encoded Ed25519 public key) at the given derivation path.
@@ -495,24 +588,6 @@ declare class DmkTransport extends Transport {
495
588
  close(): Promise<void>;
496
589
  }
497
590
 
498
- /**
499
- * Convert a DMK DeviceAction (Observable-based) into a Promise.
500
- * Handles pending -> completed/error state transitions and interaction callbacks.
501
- *
502
- * Tracks the last DMK step observed (e.g. `signer.eth.steps.blindSignTransactionFallback`)
503
- * and attaches it to the rejected error as a non-enumerable `_lastStep` property,
504
- * so upstream error classifiers can distinguish failure contexts (e.g. Blind signing
505
- * disabled vs. generic Invalid data).
506
- *
507
- * @param timeoutMs Timeout in ms. Resets each time the Observable emits (device is alive).
508
- * Pass 0 to disable. Default: 30s.
509
- * @param onRegisterCanceller Optional callback that receives a function which, when
510
- * called, unsubscribes and cancels the underlying DeviceAction
511
- * (releases DMK's IntentQueue slot). Caller is responsible
512
- * for invoking the canceller on timeout/abort scenarios.
513
- */
514
- declare function deviceActionToPromise<T>(action: DeviceAction<T>, onInteraction?: (interaction: string) => void, timeoutMs?: number, onRegisterCanceller?: (cancel: () => void) => void): Promise<T>;
515
-
516
591
  interface AppManagerOptions {
517
592
  waitMs?: number;
518
593
  maxRetries?: number;
@@ -566,30 +641,17 @@ declare class AppManager {
566
641
  private _wait;
567
642
  }
568
643
 
569
- /**
570
- * Ledger-specific Failure: adds `appName` for "the currently-open app" — a
571
- * Ledger hardware concept not shared with other vendors, so it lives here
572
- * rather than in core's generic Failure.
573
- */
574
644
  type LedgerFailure = Omit<Failure, 'payload'> & {
575
645
  payload: Failure['payload'] & {
576
646
  appName?: string;
647
+ _tag?: string;
577
648
  };
578
649
  };
579
650
  interface WrapErrorOptions {
580
- /**
581
- * Fallback app name when the raw error doesn't carry `appName` itself
582
- * (DMK signer errors don't). Used by mapLedgerError so downstream
583
- * AppNotOpen / WrongApp / AppTooOld toasts can interpolate `{appName}`.
584
- */
651
+ /** Fallback when err has no `appName` (DMK signer errors don't carry it). */
585
652
  defaultAppName?: string;
586
653
  }
587
- /**
588
- * Structurally compatible with `Failure`; writes `appName` only when provided,
589
- * so `'appName' in payload` is a reliable "has info" signal for consumers.
590
- */
591
- declare function ledgerFailure(code: HardwareErrorCode, error: string, appName?: string): LedgerFailure;
592
- /** Check if an error (or any error in its chain) represents a locked Ledger device. */
654
+ declare function ledgerFailure(code: HardwareErrorCode, error: string, appName?: string, tag?: string, params?: Record<string, unknown>): LedgerFailure;
593
655
  declare function isDeviceLockedError(err: unknown): boolean;
594
656
  /**
595
657
  * Map a Ledger DMK error to a HardwareErrorCode and human-readable message.
@@ -603,20 +665,35 @@ declare function mapLedgerError(err: unknown, opts?: WrapErrorOptions): {
603
665
  };
604
666
 
605
667
  /**
606
- * Centralised debug logger for the Ledger adapter.
607
- *
608
- * Off by default. Toggle programmatically via `setDebugEnabled(true)`.
668
+ * SDK-global event bus. Per-runtime singleton each process subscribes
669
+ * independently; cross-process hosts forward events over their own IPC.
609
670
  */
610
- /** Enable or disable debug logging at runtime. */
611
- declare function setDebugEnabled(value: boolean): void;
612
- /** Returns the current debug-enabled state. */
613
- declare function isDebugEnabled(): boolean;
671
+ type SdkLogEvent = {
672
+ type: 'log';
673
+ level: 'debug' | 'error';
674
+ /** Pre-stringified payload. */
675
+ message: string;
676
+ };
677
+ /** Add new variants here; hosts dispatch on `event.type`. */
678
+ type SdkEvent = SdkLogEvent;
679
+ type SdkEventListener = (event: SdkEvent) => void;
680
+ declare function onSdkEvent(listener: SdkEventListener): () => void;
681
+ declare function offSdkEvent(listener: SdkEventListener): void;
682
+
683
+ declare function debugLog(...args: unknown[]): void;
614
684
 
615
685
  /**
616
- * Extract the stable 4-digit HEX identifier from a Ledger BLE device name.
617
- * e.g., "Nano X 123A" -> "123A", "Ledger Nano X AB12" -> "AB12"
618
- * Returns undefined if no valid HEX suffix found.
686
+ * Ledger DMK transport identifiers that represent BLE devices.
687
+ *
688
+ * Known today:
689
+ * - "BLE": generic/web BLE descriptors
690
+ * - "RN_BLE": @ledgerhq/device-transport-kit-react-native-ble
691
+ *
692
+ * Keep the suffix check here so future DMK BLE transports (for example
693
+ * "FOO_BLE") are handled in one place instead of scattering string checks.
619
694
  */
620
- declare function extractBleHexId(name?: string): string | undefined;
695
+ declare function isLedgerDmkBleTransport(transport?: string): boolean;
696
+ declare function isLedgerBleConnectionType(connectionType?: ConnectionType): boolean;
697
+ declare function isLedgerBleDescriptor(connectionType: ConnectionType, descriptor: DeviceDescriptor): boolean;
621
698
 
622
- export { AppManager, type DeviceActionState, type DmkDiscoveredDevice, DmkTransport, LedgerAdapter, LedgerConnectorBase, type LedgerConnectorBaseOptions, LedgerDeviceManager, type LedgerFailure, SignerBtc, type SignerBtcAddress, SignerEth, type SignerEvmAddress, type SignerEvmSignature, SignerManager, SignerSol, type TransportFactory, deviceActionToPromise, extractBleHexId, isDebugEnabled, isDeviceLockedError, ledgerFailure, mapLedgerError, setDebugEnabled };
699
+ 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 };