@onekeyfe/hwk-ledger-adapter 1.1.26-alpha.105 → 1.1.26-alpha.11

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,4 +1,4 @@
1
- import { IHardwareWallet, IConnector, TransportType, IUiHandler, 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, HardwareErrorCode } from '@onekeyfe/hwk-adapter-core';
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, ConnectionType, DeviceDescriptor, ConnectorDevice, ConnectorSession, ConnectorEventType, ConnectorEventMap, DeviceChangeEvent, Failure, HardwareErrorCode } from '@onekeyfe/hwk-adapter-core';
2
2
  import { DeviceManagementKit, DeviceActionState as DeviceActionState$1, DiscoveredDevice, ExecuteDeviceActionReturnType } from '@ledgerhq/device-management-kit';
3
3
  import { Address, Signature, SignerEth as SignerEth$1, TypedData } from '@ledgerhq/device-signer-kit-ethereum';
4
4
  import { SignerBtc as SignerBtc$1 } from '@ledgerhq/device-signer-kit-bitcoin';
@@ -21,22 +21,28 @@ interface LedgerAdapterOptions {
21
21
  * - Translates IHardwareWallet method calls to connector.call() invocations
22
22
  * - Maps connector results/errors to our Response<T> format with enriched error messages
23
23
  * - Translates connector events to HardwareEventMap events
24
- * - Integrates with IUiHandler for permission flows
24
+ * - Emits `REQUEST_DEVICE_PERMISSION` for OS-level permission checks
25
25
  */
26
26
  declare class LedgerAdapter implements IHardwareWallet {
27
27
  readonly vendor: "ledger";
28
28
  private readonly connector;
29
29
  private readonly emitter;
30
- private _uiHandler;
31
30
  private readonly _handleSelectDevice;
32
31
  private _discoveredDevices;
33
32
  private _sessions;
34
33
  private readonly _uiRegistry;
34
+ private readonly _jobQueue;
35
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;
36
43
  get activeTransport(): TransportType | null;
37
44
  getAvailableTransports(): TransportType[];
38
45
  switchTransport(_type: TransportType): Promise<void>;
39
- setUiHandler(handler: Partial<IUiHandler>): void;
40
46
  init(_config?: unknown): Promise<void>;
41
47
  /**
42
48
  * Clear cached device/session state without tearing down the adapter.
@@ -52,18 +58,11 @@ declare class LedgerAdapter implements IHardwareWallet {
52
58
  getDeviceInfo(connectId: string, deviceId: string): Promise<Response<DeviceInfo>>;
53
59
  getSupportedChains(): ChainCapability[];
54
60
  private callChain;
55
- /**
56
- * Batch version of callChain — checks permission once,
57
- * fingerprint is verified on the first call inside connectorCall.
58
- */
59
- private callChainBatch;
60
61
  evmGetAddress(connectId: string, deviceId: string, params: EvmGetAddressParams): Promise<Response<EvmAddress>>;
61
- evmGetAddresses(connectId: string, deviceId: string, params: EvmGetAddressParams[], onProgress?: ProgressCallback): Promise<Response<EvmAddress[]>>;
62
62
  evmSignTransaction(connectId: string, deviceId: string, params: EvmSignTxParams): Promise<Response<EvmSignedTx>>;
63
63
  evmSignMessage(connectId: string, deviceId: string, params: EvmSignMsgParams): Promise<Response<EvmSignature>>;
64
64
  evmSignTypedData(connectId: string, deviceId: string, params: EvmSignTypedDataParams): Promise<Response<EvmSignature>>;
65
65
  btcGetAddress(connectId: string, deviceId: string, params: BtcGetAddressParams): Promise<Response<BtcAddress>>;
66
- btcGetAddresses(connectId: string, deviceId: string, params: BtcGetAddressParams[], onProgress?: ProgressCallback): Promise<Response<BtcAddress[]>>;
67
66
  btcGetPublicKey(connectId: string, deviceId: string, params: BtcGetPublicKeyParams): Promise<Response<BtcPublicKey>>;
68
67
  btcSignTransaction(connectId: string, deviceId: string, params: BtcSignTxParams): Promise<Response<BtcSignedTx>>;
69
68
  btcSignPsbt(connectId: string, deviceId: string, params: BtcSignPsbtParams): Promise<Response<BtcSignedPsbt>>;
@@ -72,18 +71,16 @@ declare class LedgerAdapter implements IHardwareWallet {
72
71
  masterFingerprint: string;
73
72
  }>>;
74
73
  solGetAddress(connectId: string, deviceId: string, params: SolGetAddressParams): Promise<Response<SolAddress>>;
75
- solGetAddresses(connectId: string, deviceId: string, params: SolGetAddressParams[], onProgress?: ProgressCallback): Promise<Response<SolAddress[]>>;
76
74
  solSignTransaction(connectId: string, deviceId: string, params: SolSignTxParams): Promise<Response<SolSignedTx>>;
77
75
  solSignMessage(connectId: string, deviceId: string, params: SolSignMsgParams): Promise<Response<SolSignature>>;
78
76
  tronGetAddress(connectId: string, deviceId: string, params: TronGetAddressParams): Promise<Response<TronAddress>>;
79
- tronGetAddresses(connectId: string, deviceId: string, params: TronGetAddressParams[], onProgress?: ProgressCallback): Promise<Response<TronAddress[]>>;
80
77
  tronSignTransaction(connectId: string, deviceId: string, params: TronSignTxParams): Promise<Response<TronSignedTx>>;
81
78
  tronSignMessage(connectId: string, deviceId: string, params: TronSignMsgParams): Promise<Response<TronSignature>>;
82
79
  on<K extends keyof HardwareEventMap>(event: K, listener: (event: HardwareEventMap[K]) => void): void;
83
80
  on(event: string, listener: DeviceEventListener): void;
84
81
  off<K extends keyof HardwareEventMap>(event: K, listener: (event: HardwareEventMap[K]) => void): void;
85
82
  off(event: string, listener: DeviceEventListener): void;
86
- cancel(connectId: string): void;
83
+ cancel(connectId?: string): void;
87
84
  getChainFingerprint(connectId: string, deviceId: string, chain: ChainForFingerprint): Promise<Response<string>>;
88
85
  /**
89
86
  * Verify fingerprint using an existing sessionId directly.
@@ -91,16 +88,20 @@ declare class LedgerAdapter implements IHardwareWallet {
91
88
  */
92
89
  private _verifyDeviceFingerprintWithSession;
93
90
  /**
94
- * Derive an address at the fixed testnet path for fingerprint generation.
95
- * Uses connectorCall (goes through ensureConnected). For public API use.
96
- */
97
- private _deriveAddressForFingerprint;
98
- /**
99
- * Derive an address using an existing sessionId directly.
100
- * Does NOT go through connectorCall safe to call inside connectorCall
101
- * without causing queue deadlock.
91
+ * Compute the chain fingerprint via a caller-supplied call strategy.
92
+ *
93
+ * Chains with a native device-side identity primitive (BTC → BIP32 master
94
+ * fingerprint) short-circuit at the top and return it verbatim, so the value
95
+ * stays reusable for higher-level use (BIP380 descriptors, PSBT signing).
96
+ *
97
+ * All other chains derive a fixed-path address and run it through
98
+ * `deriveDeviceFingerprint` to produce an opaque seed identifier.
99
+ *
100
+ * The two callers (`getChainFingerprint` / `_verifyDeviceFingerprintWithSession`)
101
+ * differ only in the underlying call mechanism, which is injected as `callMethod`
102
+ * to avoid queue deadlocks when running inside `connectorCall`.
102
103
  */
103
- private _deriveAddressWithSession;
104
+ private _computeChainFingerprint;
104
105
  /**
105
106
  * Ensure at least one device is connected and return a valid connectId.
106
107
  *
@@ -124,13 +125,38 @@ declare class LedgerAdapter implements IHardwareWallet {
124
125
  * 4. On disconnect error: clears stale session, re-connects, retries once
125
126
  */
126
127
  private connectorCall;
127
- /** Clear stale session, reconnect, and retry the call. */
128
+ /**
129
+ * Race a promise against an abort signal. If the signal fires, rejects with the
130
+ * signal's reason (or a generic Error). The underlying connector.call() cannot
131
+ * actually be cancelled on Ledger DMK, but the caller gets the abort immediately.
132
+ */
133
+ private static _abortable;
134
+ /** Throw an AbortError if signal is already aborted. */
135
+ private static _throwIfAborted;
136
+ /** Actual work done under the job queue — connection, fingerprint, call, and recovery. */
137
+ private _runConnectorCall;
138
+ /**
139
+ * Clear stale session, reconnect, and retry the call.
140
+ *
141
+ * Two-stage recovery: the inner retry first re-uses the current DMK to
142
+ * cut latency; if that still fails with a disconnect/timeout, the DMK
143
+ * itself is likely wedged (transport stuck after an abnormal teardown
144
+ * — process killed, USB yanked, browser kept the offscreen page across
145
+ * a session boundary). In that case we fully `connector.reset()` to
146
+ * force a fresh DMK + transport on the next round.
147
+ */
128
148
  private _retryWithFreshConnection;
129
149
  /**
130
- * Ensure device permission before proceeding.
131
- * - No connectId (searchDevices): check environment-level permission
132
- * - With connectId (business methods): check device-level permission
133
- * If not granted, calls onDevicePermission so the consumer can request access.
150
+ * Ensure OS-level device permission (Bluetooth / USB) before proceeding.
151
+ *
152
+ * Emits `REQUEST_DEVICE_PERMISSION` and awaits the consumer's
153
+ * `RECEIVE_DEVICE_PERMISSION` reply (60s budget covers "probe system
154
+ * prompt → user tap" plus a generous margin). If the consumer never wires
155
+ * a handler or never replies, the wait times out and the operation fails
156
+ * fast so scanners/callers don't hang silently.
157
+ *
158
+ * - No connectId (searchDevices): environment-level permission
159
+ * - With connectId (business methods): device-level permission
134
160
  */
135
161
  private _ensureDevicePermission;
136
162
  /**
@@ -140,14 +166,10 @@ declare class LedgerAdapter implements IHardwareWallet {
140
166
  private errorToFailure;
141
167
  private deviceConnectHandler;
142
168
  private deviceDisconnectHandler;
143
- private uiRequestHandler;
144
- private uiEventHandler;
169
+ private uiEventForwarder;
145
170
  private registerEventListeners;
146
171
  private unregisterEventListeners;
147
- private handleUiEvent;
148
172
  private connectorDeviceToDeviceInfo;
149
- private extractDeviceInfoFromPayload;
150
- private unknownDevice;
151
173
  }
152
174
 
153
175
  /**
@@ -184,7 +206,7 @@ declare class LedgerConnectorBase implements IConnector {
184
206
  private readonly _eventHandlers;
185
207
  private readonly _providedDmk;
186
208
  private readonly _createTransport;
187
- private readonly _connectionType;
209
+ readonly connectionType: ConnectionType;
188
210
  private _connectIdToPath;
189
211
  private _pathToConnectId;
190
212
  /** Register a connectId <-> path mapping from a device descriptor. */
@@ -193,6 +215,10 @@ declare class LedgerConnectorBase implements IConnector {
193
215
  private _getPathForConnectId;
194
216
  /** Get external connectId from DMK path. Falls back to path itself. */
195
217
  private _getConnectIdForPath;
218
+ private readonly _cancellers;
219
+ private readonly _sessionStateSubs;
220
+ private _diagDeviceListSub;
221
+ private _diagDeviceListPrev;
196
222
  /**
197
223
  * Resolves a Ledger signer kit module by package name.
198
224
  * Override via constructor to use CJS paths for Metro (React Native).
@@ -220,8 +246,31 @@ declare class LedgerConnectorBase implements IConnector {
220
246
  searchDevices(): Promise<ConnectorDevice[]>;
221
247
  connect(deviceId?: string): Promise<ConnectorSession>;
222
248
  disconnect(sessionId: string): Promise<void>;
249
+ /**
250
+ * Subscribe to DMK's per-session state observable so that any autonomous
251
+ * disconnect (USB unplug, BLE drop, device sleep, transport reset) is
252
+ * surfaced as a `device-disconnect` event — without this, the upstream
253
+ * `LedgerAdapter._sessions` map would hold a dead session entry until
254
+ * the next call hit `DeviceSessionNotFound`.
255
+ *
256
+ * Best-effort: any error subscribing is swallowed so a flaky DMK
257
+ * doesn't break the connect path.
258
+ */
259
+ private _watchSessionState;
260
+ private _unwatchSessionState;
261
+ private _handleAutonomousDisconnect;
262
+ /**
263
+ * Start a long-lived listenToAvailableDevices subscription whose only job
264
+ * is to log every emission (with diff vs previous) so we can determine
265
+ * whether DMK proactively re-emits the device list when a USB device is
266
+ * unplugged or a BLE peripheral disappears. Pure observation — does NOT
267
+ * touch any cache or emit any event. See _diagDeviceListSub comment for
268
+ * rationale.
269
+ */
270
+ private _startDiagnosticDeviceListListen;
223
271
  call(sessionId: string, method: string, params: unknown): Promise<unknown>;
224
- cancel(_sessionId: string): Promise<void>;
272
+ private _dispatch;
273
+ cancel(sessionId: string): Promise<void>;
225
274
  uiResponse(_response: UiResponseEvent): void;
226
275
  on<K extends ConnectorEventType>(event: K, handler: (data: ConnectorEventMap[K]) => void): void;
227
276
  off<K extends ConnectorEventType>(event: K, handler: (data: ConnectorEventMap[K]) => void): void;
@@ -249,6 +298,12 @@ declare class LedgerConnectorBase implements IConnector {
249
298
  private _resetSignersAndSessions;
250
299
  private _resetAll;
251
300
  protected _emit<K extends ConnectorEventType>(event: K, data: ConnectorEventMap[K]): void;
301
+ /**
302
+ * Return a per-call ctx with the chain's Ledger app name pre-bound to
303
+ * wrapError, so chain handlers don't need to repeat `{ defaultAppName: 'X' }`
304
+ * at every catch site. Falls through unchanged for unknown methods.
305
+ */
306
+ private _ctxForMethod;
252
307
  private _wrapError;
253
308
  }
254
309
 
@@ -323,6 +378,30 @@ interface SignerBtcAddress {
323
378
  address: string;
324
379
  }
325
380
 
381
+ /** Optional context attached to the rejection when a canceller fires. */
382
+ interface CancelReason {
383
+ code?: number;
384
+ tag?: string;
385
+ message?: string;
386
+ }
387
+ /**
388
+ * Convert a DMK DeviceAction (Observable-based) into a Promise.
389
+ * Handles pending -> completed/error state transitions and interaction callbacks.
390
+ *
391
+ * Tracks the last DMK step observed (e.g. `signer.eth.steps.blindSignTransactionFallback`)
392
+ * and attaches it to the rejected error as a non-enumerable `_lastStep` property,
393
+ * so upstream error classifiers can distinguish failure contexts (e.g. Blind signing
394
+ * disabled vs. generic Invalid data).
395
+ *
396
+ * @param timeoutMs Timeout in ms. Resets each time the Observable emits (device is alive).
397
+ * Pass 0 to disable. Default: 30s.
398
+ * @param onRegisterCanceller Optional callback that receives a function which, when
399
+ * called, unsubscribes and cancels the underlying DeviceAction
400
+ * (releases DMK's IntentQueue slot). Caller is responsible
401
+ * for invoking the canceller on timeout/abort scenarios.
402
+ */
403
+ declare function deviceActionToPromise<T>(action: DeviceAction<T>, onInteraction?: (interaction: string) => void, timeoutMs?: number, onRegisterCanceller?: (cancel: (reason?: CancelReason) => void) => void): Promise<T>;
404
+
326
405
  /**
327
406
  * Wraps Ledger's SDK signer (Observable-based DeviceActions) into
328
407
  * a simple async interface returning plain serializable data.
@@ -331,6 +410,12 @@ declare class SignerEth {
331
410
  private readonly _sdk;
332
411
  onInteraction?: (interaction: string) => void;
333
412
  constructor(_sdk: SignerEth$1);
413
+ /**
414
+ * Optional callback registered per-call so the caller can obtain a canceller
415
+ * for the underlying DeviceAction. Caller can invoke it to release DMK's
416
+ * IntentQueue slot and unsubscribe from the action's observable.
417
+ */
418
+ onRegisterCanceller?: (cancel: (reason?: CancelReason) => void) => void;
334
419
  getAddress(derivationPath: string, options?: {
335
420
  checkOnDevice?: boolean;
336
421
  }): Promise<SignerEvmAddress>;
@@ -348,16 +433,16 @@ type SignerEthBuilderFn = (args: {
348
433
  build(): SignerEth$1;
349
434
  }>;
350
435
  /**
351
- * Manages per-sessionId SignerEth instances.
352
- * Creates on demand, caches for reuse, invalidates on session change.
436
+ * Per-sessionId SignerEth factory. Builds fresh on every call — DMK signers
437
+ * hold DeviceAction state that isn't safe to reuse, so `invalidate` /
438
+ * `clearAll` are kept as no-op lifecycle hooks for callers.
353
439
  */
354
440
  declare class SignerManager {
355
- private readonly _cache;
356
441
  private readonly _dmk;
357
442
  private readonly _builderFn;
358
443
  constructor(dmk: DeviceManagementKit, builderFn?: SignerEthBuilderFn);
359
444
  getOrCreate(sessionId: string): Promise<SignerEth>;
360
- invalidate(sessionId: string): void;
445
+ invalidate(_sessionId: string): void;
361
446
  clearAll(): void;
362
447
  private static _defaultBuilder;
363
448
  }
@@ -373,6 +458,7 @@ type BtcMessageOptions = Parameters<SignerBtc$1['signMessage']>[2];
373
458
  declare class SignerBtc {
374
459
  private readonly _sdk;
375
460
  onInteraction?: (interaction: string) => void;
461
+ onRegisterCanceller?: (cancel: (reason?: CancelReason) => void) => void;
376
462
  constructor(_sdk: SignerBtc$1);
377
463
  getWalletAddress(wallet: BtcWallet, addressIndex: number, options?: {
378
464
  checkOnDevice?: boolean;
@@ -418,6 +504,7 @@ type SolMsgOptions = Parameters<SignerSolana['signMessage']>[2];
418
504
  declare class SignerSol {
419
505
  private readonly _sdk;
420
506
  onInteraction?: (interaction: string) => void;
507
+ onRegisterCanceller?: (cancel: (reason?: CancelReason) => void) => void;
421
508
  constructor(_sdk: SignerSolana);
422
509
  /**
423
510
  * Get the Solana address (base58-encoded Ed25519 public key) at the given derivation path.
@@ -458,20 +545,6 @@ declare class DmkTransport extends Transport {
458
545
  close(): Promise<void>;
459
546
  }
460
547
 
461
- /**
462
- * Convert a DMK DeviceAction (Observable-based) into a Promise.
463
- * Handles pending -> completed/error state transitions and interaction callbacks.
464
- *
465
- * Tracks the last DMK step observed (e.g. `signer.eth.steps.blindSignTransactionFallback`)
466
- * and attaches it to the rejected error as a non-enumerable `_lastStep` property,
467
- * so upstream error classifiers can distinguish failure contexts (e.g. Blind signing
468
- * disabled vs. generic Invalid data).
469
- *
470
- * @param timeoutMs Timeout in ms. Resets each time the Observable emits (device is alive).
471
- * Pass 0 to disable. Default: 30s.
472
- */
473
- declare function deviceActionToPromise<T>(action: DeviceAction<T>, onInteraction?: (interaction: string) => void, timeoutMs?: number): Promise<T>;
474
-
475
548
  interface AppManagerOptions {
476
549
  waitMs?: number;
477
550
  maxRetries?: number;
@@ -501,9 +574,16 @@ declare class AppManager {
501
574
  * 5. Poll until the device confirms the target app is running.
502
575
  */
503
576
  /**
504
- * @param onConfirmOnDevice Called after OpenAppCommand succeeds
505
- * the device is now showing a confirmation prompt to the user.
506
- * NOT called if the app is already open or if the app is not installed.
577
+ * @param onConfirmOnDevice Called BEFORE OpenAppCommand is issued the
578
+ * device is about to display "Open <app>" on screen and wait for the
579
+ * user's button press. UI consumers should show their "open app" prompt
580
+ * in response. NOT called when the target app is already open (no user
581
+ * interaction needed in that case).
582
+ *
583
+ * Important: OpenAppCommand is blocking. It does not resolve until the user
584
+ * has physically confirmed on the device, so anything that runs AFTER
585
+ * `await this._openApp(...)` lands AFTER the prompt is already gone.
586
+ * Hence the callback must fire BEFORE that await.
507
587
  */
508
588
  ensureAppOpen(sessionId: string, targetAppName: string, onConfirmOnDevice?: () => void): Promise<void>;
509
589
  private _getCurrentApp;
@@ -518,16 +598,63 @@ declare class AppManager {
518
598
  private _wait;
519
599
  }
520
600
 
601
+ /**
602
+ * Ledger-specific Failure: adds `appName` for "the currently-open app" — a
603
+ * Ledger hardware concept not shared with other vendors, so it lives here
604
+ * rather than in core's generic Failure.
605
+ */
606
+ type LedgerFailure = Omit<Failure, 'payload'> & {
607
+ payload: Failure['payload'] & {
608
+ appName?: string;
609
+ };
610
+ };
611
+ interface WrapErrorOptions {
612
+ /**
613
+ * Fallback app name when the raw error doesn't carry `appName` itself
614
+ * (DMK signer errors don't). Used by mapLedgerError so downstream
615
+ * AppNotOpen / WrongApp / AppTooOld toasts can interpolate `{appName}`.
616
+ */
617
+ defaultAppName?: string;
618
+ }
619
+ /**
620
+ * Structurally compatible with `Failure`; writes `appName` only when provided,
621
+ * so `'appName' in payload` is a reliable "has info" signal for consumers.
622
+ */
623
+ declare function ledgerFailure(code: HardwareErrorCode, error: string, appName?: string): LedgerFailure;
521
624
  /** Check if an error (or any error in its chain) represents a locked Ledger device. */
522
625
  declare function isDeviceLockedError(err: unknown): boolean;
523
626
  /**
524
- * Map a Ledger DMK error to a HardwareErrorCode and human-readable message
525
- * with actionable recovery information for the caller.
627
+ * Map a Ledger DMK error to a HardwareErrorCode and human-readable message.
628
+ * `opts.defaultAppName` fills `appName` when the raw error doesn't carry it
629
+ * (DMK signer errors don't).
526
630
  */
527
- declare function mapLedgerError(err: unknown): {
631
+ declare function mapLedgerError(err: unknown, opts?: WrapErrorOptions): {
528
632
  code: HardwareErrorCode;
529
633
  message: string;
530
634
  appName?: string;
531
635
  };
532
636
 
533
- export { AppManager, type DeviceActionState, type DmkDiscoveredDevice, DmkTransport, LedgerAdapter, LedgerConnectorBase, type LedgerConnectorBaseOptions, LedgerDeviceManager, SignerBtc, type SignerBtcAddress, SignerEth, type SignerEvmAddress, type SignerEvmSignature, SignerManager, SignerSol, type TransportFactory, deviceActionToPromise, isDeviceLockedError, mapLedgerError };
637
+ /**
638
+ * SDK-global event bus. Per-runtime singleton — each process subscribes
639
+ * independently; cross-process hosts forward events over their own IPC.
640
+ */
641
+ type SdkLogEvent = {
642
+ type: 'log';
643
+ level: 'debug' | 'error';
644
+ /** Pre-stringified payload. */
645
+ message: string;
646
+ };
647
+ /** Add new variants here; hosts dispatch on `event.type`. */
648
+ type SdkEvent = SdkLogEvent;
649
+ type SdkEventListener = (event: SdkEvent) => void;
650
+ declare function onSdkEvent(listener: SdkEventListener): () => void;
651
+ declare function offSdkEvent(listener: SdkEventListener): void;
652
+
653
+ /**
654
+ * Extract the stable 4-digit HEX identifier from a Ledger BLE device name.
655
+ * e.g., "Nano X 123A" -> "123A", "Ledger Nano X AB12" -> "AB12"
656
+ * Returns undefined if no valid HEX suffix found.
657
+ */
658
+ declare function extractBleHexId(name?: string): string | undefined;
659
+
660
+ 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, ledgerFailure, mapLedgerError, offSdkEvent, onSdkEvent };