@onekeyfe/hwk-ledger-adapter 1.1.26-alpha.106 → 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.
@@ -128,13 +125,38 @@ declare class LedgerAdapter implements IHardwareWallet {
128
125
  * 4. On disconnect error: clears stale session, re-connects, retries once
129
126
  */
130
127
  private connectorCall;
131
- /** 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
+ */
132
148
  private _retryWithFreshConnection;
133
149
  /**
134
- * Ensure device permission before proceeding.
135
- * - No connectId (searchDevices): check environment-level permission
136
- * - With connectId (business methods): check device-level permission
137
- * 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
138
160
  */
139
161
  private _ensureDevicePermission;
140
162
  /**
@@ -144,14 +166,10 @@ declare class LedgerAdapter implements IHardwareWallet {
144
166
  private errorToFailure;
145
167
  private deviceConnectHandler;
146
168
  private deviceDisconnectHandler;
147
- private uiRequestHandler;
148
- private uiEventHandler;
169
+ private uiEventForwarder;
149
170
  private registerEventListeners;
150
171
  private unregisterEventListeners;
151
- private handleUiEvent;
152
172
  private connectorDeviceToDeviceInfo;
153
- private extractDeviceInfoFromPayload;
154
- private unknownDevice;
155
173
  }
156
174
 
157
175
  /**
@@ -188,7 +206,7 @@ declare class LedgerConnectorBase implements IConnector {
188
206
  private readonly _eventHandlers;
189
207
  private readonly _providedDmk;
190
208
  private readonly _createTransport;
191
- private readonly _connectionType;
209
+ readonly connectionType: ConnectionType;
192
210
  private _connectIdToPath;
193
211
  private _pathToConnectId;
194
212
  /** Register a connectId <-> path mapping from a device descriptor. */
@@ -197,6 +215,10 @@ declare class LedgerConnectorBase implements IConnector {
197
215
  private _getPathForConnectId;
198
216
  /** Get external connectId from DMK path. Falls back to path itself. */
199
217
  private _getConnectIdForPath;
218
+ private readonly _cancellers;
219
+ private readonly _sessionStateSubs;
220
+ private _diagDeviceListSub;
221
+ private _diagDeviceListPrev;
200
222
  /**
201
223
  * Resolves a Ledger signer kit module by package name.
202
224
  * Override via constructor to use CJS paths for Metro (React Native).
@@ -224,8 +246,31 @@ declare class LedgerConnectorBase implements IConnector {
224
246
  searchDevices(): Promise<ConnectorDevice[]>;
225
247
  connect(deviceId?: string): Promise<ConnectorSession>;
226
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;
227
271
  call(sessionId: string, method: string, params: unknown): Promise<unknown>;
228
- cancel(_sessionId: string): Promise<void>;
272
+ private _dispatch;
273
+ cancel(sessionId: string): Promise<void>;
229
274
  uiResponse(_response: UiResponseEvent): void;
230
275
  on<K extends ConnectorEventType>(event: K, handler: (data: ConnectorEventMap[K]) => void): void;
231
276
  off<K extends ConnectorEventType>(event: K, handler: (data: ConnectorEventMap[K]) => void): void;
@@ -253,6 +298,12 @@ declare class LedgerConnectorBase implements IConnector {
253
298
  private _resetSignersAndSessions;
254
299
  private _resetAll;
255
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;
256
307
  private _wrapError;
257
308
  }
258
309
 
@@ -327,6 +378,30 @@ interface SignerBtcAddress {
327
378
  address: string;
328
379
  }
329
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
+
330
405
  /**
331
406
  * Wraps Ledger's SDK signer (Observable-based DeviceActions) into
332
407
  * a simple async interface returning plain serializable data.
@@ -335,6 +410,12 @@ declare class SignerEth {
335
410
  private readonly _sdk;
336
411
  onInteraction?: (interaction: string) => void;
337
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;
338
419
  getAddress(derivationPath: string, options?: {
339
420
  checkOnDevice?: boolean;
340
421
  }): Promise<SignerEvmAddress>;
@@ -352,16 +433,16 @@ type SignerEthBuilderFn = (args: {
352
433
  build(): SignerEth$1;
353
434
  }>;
354
435
  /**
355
- * Manages per-sessionId SignerEth instances.
356
- * 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.
357
439
  */
358
440
  declare class SignerManager {
359
- private readonly _cache;
360
441
  private readonly _dmk;
361
442
  private readonly _builderFn;
362
443
  constructor(dmk: DeviceManagementKit, builderFn?: SignerEthBuilderFn);
363
444
  getOrCreate(sessionId: string): Promise<SignerEth>;
364
- invalidate(sessionId: string): void;
445
+ invalidate(_sessionId: string): void;
365
446
  clearAll(): void;
366
447
  private static _defaultBuilder;
367
448
  }
@@ -377,6 +458,7 @@ type BtcMessageOptions = Parameters<SignerBtc$1['signMessage']>[2];
377
458
  declare class SignerBtc {
378
459
  private readonly _sdk;
379
460
  onInteraction?: (interaction: string) => void;
461
+ onRegisterCanceller?: (cancel: (reason?: CancelReason) => void) => void;
380
462
  constructor(_sdk: SignerBtc$1);
381
463
  getWalletAddress(wallet: BtcWallet, addressIndex: number, options?: {
382
464
  checkOnDevice?: boolean;
@@ -422,6 +504,7 @@ type SolMsgOptions = Parameters<SignerSolana['signMessage']>[2];
422
504
  declare class SignerSol {
423
505
  private readonly _sdk;
424
506
  onInteraction?: (interaction: string) => void;
507
+ onRegisterCanceller?: (cancel: (reason?: CancelReason) => void) => void;
425
508
  constructor(_sdk: SignerSolana);
426
509
  /**
427
510
  * Get the Solana address (base58-encoded Ed25519 public key) at the given derivation path.
@@ -462,20 +545,6 @@ declare class DmkTransport extends Transport {
462
545
  close(): Promise<void>;
463
546
  }
464
547
 
465
- /**
466
- * Convert a DMK DeviceAction (Observable-based) into a Promise.
467
- * Handles pending -> completed/error state transitions and interaction callbacks.
468
- *
469
- * Tracks the last DMK step observed (e.g. `signer.eth.steps.blindSignTransactionFallback`)
470
- * and attaches it to the rejected error as a non-enumerable `_lastStep` property,
471
- * so upstream error classifiers can distinguish failure contexts (e.g. Blind signing
472
- * disabled vs. generic Invalid data).
473
- *
474
- * @param timeoutMs Timeout in ms. Resets each time the Observable emits (device is alive).
475
- * Pass 0 to disable. Default: 30s.
476
- */
477
- declare function deviceActionToPromise<T>(action: DeviceAction<T>, onInteraction?: (interaction: string) => void, timeoutMs?: number): Promise<T>;
478
-
479
548
  interface AppManagerOptions {
480
549
  waitMs?: number;
481
550
  maxRetries?: number;
@@ -505,9 +574,16 @@ declare class AppManager {
505
574
  * 5. Poll until the device confirms the target app is running.
506
575
  */
507
576
  /**
508
- * @param onConfirmOnDevice Called after OpenAppCommand succeeds
509
- * the device is now showing a confirmation prompt to the user.
510
- * 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.
511
587
  */
512
588
  ensureAppOpen(sessionId: string, targetAppName: string, onConfirmOnDevice?: () => void): Promise<void>;
513
589
  private _getCurrentApp;
@@ -522,16 +598,63 @@ declare class AppManager {
522
598
  private _wait;
523
599
  }
524
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;
525
624
  /** Check if an error (or any error in its chain) represents a locked Ledger device. */
526
625
  declare function isDeviceLockedError(err: unknown): boolean;
527
626
  /**
528
- * Map a Ledger DMK error to a HardwareErrorCode and human-readable message
529
- * 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).
530
630
  */
531
- declare function mapLedgerError(err: unknown): {
631
+ declare function mapLedgerError(err: unknown, opts?: WrapErrorOptions): {
532
632
  code: HardwareErrorCode;
533
633
  message: string;
534
634
  appName?: string;
535
635
  };
536
636
 
537
- 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 };