@onekeyfe/hwk-ledger-adapter 1.2.0-alpha.2 → 1.2.0-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 +0 -6
- package/dist/index.d.ts +0 -6
- package/dist/index.js +220 -723
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +151 -655
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/adapter/LedgerAdapter.ts","../src/errors.ts","../src/adapter/methods/allNetworkGetAddress.ts","../src/utils/sdkEventBus.ts","../src/utils/debugLog.ts","../src/utils/ledgerDmkTransport.ts","../src/connector/LedgerConnectorBase.ts","../src/device/LedgerDeviceManager.ts","../src/signer/SignerManager.ts","../src/signer/SignerEth.ts","../src/signer/deviceActionToPromise.ts","../src/connector/chains/evm.ts","../src/connector/chains/utils.ts","../src/connector/chains/btc.ts","../src/signer/SignerBtc.ts","../src/connector/chains/sol.ts","../src/signer/SignerSol.ts","../src/connector/chains/tron.ts","../src/connector/chains/legacyChainCall.ts","../src/app/AppManager.ts","../src/transport/DmkTransport.ts","../src/device-apps/customActions.ts","../src/device-apps/errors.ts","../src/device-apps/DeviceApps.ts","../src/device-apps/DeviceAppsManager.ts"],"sourcesContent":["// Adapter\nexport { LedgerAdapter } from './adapter/LedgerAdapter';\n\n// Connector base class (used by connector packages)\nexport { LedgerConnectorBase } from './connector/LedgerConnectorBase';\nexport type { TransportFactory, LedgerConnectorBaseOptions } from './connector/LedgerConnectorBase';\n\n// Device management (used by connectors)\nexport { LedgerDeviceManager } from './device/LedgerDeviceManager';\n\n// Signer (used by connectors)\nexport { SignerManager } from './signer/SignerManager';\nexport { SignerEth } from './signer/SignerEth';\nexport { SignerBtc } from './signer/SignerBtc';\nexport { SignerSol } from './signer/SignerSol';\nexport { DmkTransport } from './transport/DmkTransport';\nexport { deviceActionToPromise } from './signer/deviceActionToPromise';\n\n// App management\nexport { AppManager } from './app/AppManager';\n\n// Types\nexport type {\n DmkDiscoveredDevice,\n DeviceActionState,\n SignerEvmAddress,\n SignerEvmSignature,\n SignerBtcAddress,\n} from './types';\n\n// Errors\nexport { isDeviceLockedError, ledgerFailure, mapLedgerError } from './errors';\nexport type { LedgerFailure } from './errors';\n\n// SDK-global event bus (logs today; extensible for firmware progress / etc.)\nexport { onSdkEvent, offSdkEvent } from './utils/sdkEventBus';\nexport type { SdkEvent, SdkEventListener, SdkLogEvent } from './utils/sdkEventBus';\n\n// BLE utilities (shared by connector packages)\nexport { debugLog } from './utils/debugLog';\nexport {\n isLedgerBleConnectionType,\n isLedgerBleDescriptor,\n isLedgerDmkBleTransport,\n} from './utils/ledgerDmkTransport';\n","import {\n CHAIN_FINGERPRINT_PATHS,\n DEVICE,\n DeviceJobQueue,\n EConnectorInteraction,\n HardwareErrorCode,\n TypedEventEmitter,\n UI_REQUEST,\n UI_REQUEST_PREEMPTED_TAG,\n UiRequestRegistry,\n createHwkError,\n deriveDeviceFingerprint,\n failure,\n rehydrateConnectorError,\n success,\n} from '@onekeyfe/hwk-adapter-core';\n\nimport {\n ERROR_TAG,\n createMultipleUsbLedgerDevicesError,\n isAppNotInstalledError,\n isConnectionLevelError,\n isDeviceDisconnectedError,\n isDeviceLockedError,\n isDeviceNotAdvertisingError,\n isStuckAppStateError,\n isTimeoutError,\n ledgerFailure,\n mapLedgerError,\n} from '../errors';\nimport { createAllNetworkGetAddress } from './methods/allNetworkGetAddress';\nimport { isLedgerBleConnectionType } from '../utils/ledgerDmkTransport';\nimport { debugError, debugLog } from '../utils/debugLog';\n\nimport type { LedgerInstallAppContext } from './methods/allNetworkGetAddress';\nimport type { AppMetadata, FirmwareVersion, LedgerDeviceInfo } from '../device-apps/DeviceApps';\nimport type {\n BtcAddress,\n BtcGetAddressParams,\n BtcGetPublicKeyParams,\n BtcPublicKey,\n BtcSignMsgParams,\n BtcSignPsbtParams,\n BtcSignTxParams,\n BtcSignature,\n BtcSignedPsbt,\n BtcSignedTx,\n ChainCapability,\n ChainForFingerprint,\n ConnectorCallResult,\n ConnectorDevice,\n ConnectorUiEvent,\n DeviceEventListener,\n DeviceInfo,\n DevicePermissionResponse,\n EvmAddress,\n EvmGetAddressParams,\n EvmSignMsgParams,\n EvmSignTxParams,\n EvmSignTypedDataParams,\n EvmSignature,\n EvmSignedTx,\n HardwareEvent,\n HardwareEventMap,\n ICommonCallParams,\n IConnector,\n IHardwareWallet,\n Response,\n SearchDevicesOptions,\n SolAddress,\n SolGetAddressParams,\n SolSignMsgParams,\n SolSignTxParams,\n SolSignature,\n SolSignedTx,\n TransportType,\n TronAddress,\n TronGetAddressParams,\n TronSignMsgParams,\n TronSignTxParams,\n TronSignature,\n TronSignedTx,\n UiResponseEvent,\n} from '@onekeyfe/hwk-adapter-core';\n\n/**\n * Result of `_verifyDeviceFingerprint`.\n *\n * On mismatch carries both the stored (expected) fingerprint and the\n * live (actual) one derived from the physically connected device.\n * Callers turn this into a `DeviceMismatch` failure via `formatDeviceMismatchError`.\n */\ntype IFingerprintVerifyResult =\n | { success: true }\n | { success: false; expected: string; actual: string };\n\ntype ConnectorCallFingerprint = {\n chain: ChainForFingerprint;\n deviceId: string;\n skipFingerprint: boolean;\n};\n\n// Fingerprints are deterministic 16-char hashes of fixed testnet paths,\n// not secrets — safe to log.\nfunction formatDeviceMismatchError(expected: string, actual: string): string {\n return `Wrong device: expected ${expected}, got ${actual}`;\n}\n\n/**\n * Ledger Bitcoin App constant `MAX_BIP44_ACCOUNT_RECOMMENDED`. Account index >=\n * this triggers `SW_NOT_SUPPORTED (0x6a82)` unless the call sets\n * `display=true`. See app-bitcoin-new src/handler/get_extended_pubkey.c.\n */\nconst BTC_HIGH_INDEX_THRESHOLD = 100;\n\nfunction btcAccountIndexFromPath(path: string): number | null {\n const segments = path.replace(/^m\\//, '').split('/');\n if (segments.length < 3) return null;\n const accountSeg = segments[2].replace(/['h]$/i, '');\n const accountIndex = parseInt(accountSeg, 10);\n return Number.isFinite(accountIndex) ? accountIndex : null;\n}\n\nexport class LedgerAdapter implements IHardwareWallet {\n readonly vendor = 'ledger' as const;\n\n private readonly connector: IConnector;\n\n private readonly emitter = new TypedEventEmitter<HardwareEventMap>();\n\n private _discoveredDevices = new Map<string, DeviceInfo>();\n\n private _sessions = new Map<string, string>();\n\n private readonly _uiRegistry = new UiRequestRegistry();\n\n // BTC App rejects account index >= 100 unless display=true. Cached per\n // adapter instance: first 100+ path asks the user once via UI request,\n // subsequent 100+ paths in the same session auto-promote silently.\n // The Ledger device itself still requires a per-call confirmation — that's\n // the Ledger app's safety boundary, not ours to bypass.\n private _btcHighIndexConfirmedThisSession = false;\n\n // Pure FIFO queue. New jobs chain onto the tail and run in order. The\n // queue is intentionally passive: it does not arbitrate, does not ask\n // the user. Callers wanting \"interrupt current?\" semantics must do so\n // explicitly via `getActiveJob()` + `forceCancelActive()` from the UI\n // layer. USB transports can't read multiple devices in parallel, and\n // BLE-only parallelism isn't worth the coordination cost.\n private readonly _jobQueue: DeviceJobQueue;\n\n // Shared across concurrent callers — only `cancel()` aborts.\n private _doConnectAbortController: AbortController | null = null;\n\n // Default for commonParams.autoInstallApp when a call doesn't specify it,\n // so the host can opt the whole adapter in once instead of per call.\n private readonly _defaultAutoInstallApp: boolean;\n\n constructor(connector: IConnector, options?: { autoInstallApp?: boolean }) {\n this.connector = connector;\n this._defaultAutoInstallApp = options?.autoInstallApp ?? false;\n this._jobQueue = new DeviceJobQueue();\n this.registerEventListeners();\n }\n\n // Transport\n get activeTransport(): TransportType | null {\n return isLedgerBleConnectionType(this.connector.connectionType) ? 'ble' : 'hid';\n }\n\n getAvailableTransports(): TransportType[] {\n return this.activeTransport ? [this.activeTransport] : [];\n }\n\n // Connector is bound at construction; switching requires a new adapter.\n switchTransport(_type: TransportType): Promise<void> {\n return Promise.resolve();\n }\n\n // Lifecycle\n init(_config?: unknown): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * Clear cached device/session state without tearing down the adapter.\n * Call before retrying after errors or when the device state may be stale.\n * The next operation will re-discover and re-connect automatically.\n */\n resetState(): void {\n this._discoveredDevices.clear();\n this._sessions.clear();\n this._connectingPromise = null;\n this._uiRegistry.reset();\n this._jobQueue.clear();\n this._btcHighIndexConfirmedThisSession = false;\n }\n\n async dispose(): Promise<void> {\n this._uiRegistry.reset();\n this._jobQueue.clear();\n this.unregisterEventListeners();\n this.connector.reset();\n this._discoveredDevices.clear();\n this._sessions.clear();\n this._btcHighIndexConfirmedThisSession = false;\n this.emitter.removeAllListeners();\n }\n\n uiResponse(response: UiResponseEvent): void {\n this._uiRegistry.resolve(response.type, response.payload);\n }\n\n // ---------------------------------------------------------------------------\n // Device management\n // ---------------------------------------------------------------------------\n\n async searchDevices(options?: SearchDevicesOptions): Promise<DeviceInfo[]> {\n debugLog('[LedgerAdapter][REQ]', { method: 'searchDevices', params: options });\n try {\n if (options?.resetSession) {\n this._doConnectAbortController?.abort();\n this._sessions.clear();\n this._connectingPromise = null;\n this._doConnectAbortController = null;\n this._btcHighIndexConfirmedThisSession = false;\n }\n\n await this._ensureDevicePermission();\n\n const devices = await this.connector.searchDevices();\n\n // Replace cache with this round's raw result. DMK paths used as connectId\n // on USB are ephemeral — incremental writes leave stale entries.\n this._discoveredDevices.clear();\n for (const d of devices) {\n if (d.connectId) {\n this._discoveredDevices.set(d.connectId, this.connectorDeviceToDeviceInfo(d));\n }\n }\n\n if (this._discoveredDevices.size === 0) {\n await this._ensureDevicePermission();\n }\n\n const result = Array.from(this._discoveredDevices.values());\n debugLog('[LedgerAdapter][RES]', {\n method: 'searchDevices',\n success: true,\n payload: result,\n });\n return result;\n } catch (err) {\n const e = err as Record<string, unknown> | null | undefined;\n debugLog('[LedgerAdapter][RES]', {\n method: 'searchDevices',\n success: false,\n error: { message: e?.message, _tag: e?._tag, code: e?.code ?? e?.errorCode },\n });\n throw err;\n }\n }\n\n // USB single-session invariant: evict all sessions, best-effort (see connectDevice).\n private async _evictAllSessions(): Promise<void> {\n if (this._sessions.size === 0) return;\n const stale = [...this._sessions.values()];\n this._sessions.clear();\n for (const sid of stale) {\n try {\n await this.connector.disconnect(sid);\n } catch {\n // best-effort\n }\n }\n }\n\n // Layer 2 retry budget after connection-class error. Each round delegates\n // to Layer 1 (which owns the unlock prompt). Layer 2 never emits UI itself.\n private static readonly MAX_BUSINESS_RETRY_BUDGET = 3;\n\n // Stuck-app (APDU 0x6901) retry pause. Ledger Stax often returns 6901 when\n // OpenAppCommand lands mid-transition right after CloseApp; a short wait\n // lets the device finish its UI animation before we retry once.\n private static readonly STUCK_APP_RETRY_DELAY_MS = 500;\n\n // Layer 1 confirm budget. After N failed Confirm cycles (user keeps clicking\n // Confirm but device never shows up / never unlocks), throw DeviceNotFound\n // instead of looping forever.\n private static readonly MAX_DOCONNECT_CONFIRMS = 3;\n\n // Cached cancel reason — used as fallback when signal.reason isn't\n // populated by the runtime (Hermes/RN). Set in cancel(), cleared shortly.\n private _lastCancelReason: Error | undefined;\n\n // Throttle AppInstallProgress by progress delta — DMK streams much faster\n // than UIs need. Final frame (progress >= 1) always passes.\n private static readonly APP_INSTALL_PROGRESS_MIN_DELTA = 0.05;\n\n private _installProgressLastEmittedValue = -Infinity;\n\n private _installProgressLastKey: string | undefined;\n\n private static _createDeviceBusyError(method: string): Error {\n return Object.assign(new Error(`Ledger device is busy while calling ${method}`), {\n code: HardwareErrorCode.DeviceBusy,\n });\n }\n\n async connectDevice(connectId: string): Promise<Response<string>> {\n debugLog('[LedgerAdapter][REQ]', { method: 'connectDevice', connectId, params: { connectId } });\n try {\n if (isLedgerBleConnectionType(this.connector.connectionType) && !connectId) {\n throw Object.assign(new Error('Ledger BLE connectId is required.'), {\n code: HardwareErrorCode.DeviceNotFound,\n });\n }\n\n // USB single-session invariant: evict any stale session before opening\n // a new one — guards ensureConnected's ambient fallback against ghosts.\n if (!isLedgerBleConnectionType(this.connector.connectionType)) {\n await this._evictAllSessions();\n }\n\n await this._ensureDevicePermission(connectId);\n\n const session = await this.connector.connect(connectId);\n this._sessions.set(connectId, session.sessionId);\n\n if (session.deviceInfo) {\n this._discoveredDevices.set(connectId, session.deviceInfo);\n }\n\n const result = success(connectId);\n debugLog('[LedgerAdapter][RES]', { method: 'connectDevice', success: true, payload: result });\n return result;\n } catch (err) {\n const failureResult = this.errorToFailure<string>(err);\n debugLog('[LedgerAdapter][RES]', {\n method: 'connectDevice',\n success: false,\n payload: failureResult,\n });\n return failureResult;\n }\n }\n\n async disconnectDevice(connectId: string): Promise<void> {\n debugLog('[LedgerAdapter][REQ]', {\n method: 'disconnectDevice',\n connectId,\n params: { connectId },\n });\n try {\n const sessionId = this._sessions.get(connectId);\n if (sessionId) {\n await this.connector.disconnect(sessionId);\n this._sessions.delete(connectId);\n }\n debugLog('[LedgerAdapter][RES]', { method: 'disconnectDevice', success: true });\n } catch (err) {\n const e = err as Record<string, unknown> | null | undefined;\n debugLog('[LedgerAdapter][RES]', {\n method: 'disconnectDevice',\n success: false,\n error: { message: e?.message, _tag: e?._tag, code: e?.code ?? e?.errorCode },\n });\n throw err;\n }\n }\n\n async getDeviceInfo(connectId: string, deviceId: string): Promise<Response<DeviceInfo>> {\n debugLog('[LedgerAdapter][REQ]', {\n method: 'getDeviceInfo',\n connectId,\n params: { connectId, deviceId },\n });\n try {\n await this._ensureDevicePermission(connectId, deviceId);\n\n // Look up the device in the cache populated by event handlers / searchDevices.\n // Try connectId first (the USB path), then fall back to scanning by deviceId.\n const cached =\n this._discoveredDevices.get(connectId) ??\n Array.from(this._discoveredDevices.values()).find(d => d.deviceId === deviceId);\n\n if (cached) {\n const result = success(cached);\n debugLog('[LedgerAdapter][RES]', {\n method: 'getDeviceInfo',\n success: true,\n payload: result,\n });\n return result;\n }\n\n const notFound = failure(\n HardwareErrorCode.DeviceNotFound,\n 'Device not found in cache. Call searchDevices() or wait for a device-connected event first.'\n );\n debugLog('[LedgerAdapter][RES]', {\n method: 'getDeviceInfo',\n success: false,\n payload: notFound,\n });\n return notFound;\n } catch (err) {\n const e = err as Record<string, unknown> | null | undefined;\n debugLog('[LedgerAdapter][RES]', {\n method: 'getDeviceInfo',\n success: false,\n error: { message: e?.message, _tag: e?._tag, code: e?.code ?? e?.errorCode },\n });\n throw err;\n }\n }\n\n getSupportedChains(): ChainCapability[] {\n return ['evm', 'btc', 'sol', 'tron'];\n }\n\n allNetworkGetAddress = createAllNetworkGetAddress({\n callChain: this.callChain.bind(this),\n getChainFingerprint: (connectId, chain) => this.getChainFingerprint(connectId, '', chain),\n });\n\n // ---------------------------------------------------------------------------\n // Chain call helper\n // ---------------------------------------------------------------------------\n\n private async callChain<T>(\n connectId: string,\n deviceId: string,\n chain: string,\n method: string,\n params: unknown,\n commonParams?: ICommonCallParams,\n skipFingerprint = false,\n installContext?: LedgerInstallAppContext\n ): Promise<Response<T>> {\n try {\n const result = await this.connectorCall(\n connectId,\n method,\n params,\n {\n chain: chain as ChainForFingerprint,\n deviceId,\n skipFingerprint,\n },\n undefined,\n commonParams,\n installContext\n );\n return success(result as T);\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n // ---------------------------------------------------------------------------\n // EVM chain methods\n // ---------------------------------------------------------------------------\n\n evmGetAddress(\n connectId: string,\n deviceId: string,\n params: EvmGetAddressParams,\n commonParams?: ICommonCallParams\n ) {\n return this.callChain<EvmAddress>(\n connectId,\n deviceId,\n 'evm',\n 'evmGetAddress',\n params,\n commonParams\n );\n }\n\n evmSignTransaction(\n connectId: string,\n deviceId: string,\n params: EvmSignTxParams,\n commonParams?: ICommonCallParams\n ) {\n return this.callChain<EvmSignedTx>(\n connectId,\n deviceId,\n 'evm',\n 'evmSignTransaction',\n params,\n commonParams\n );\n }\n\n evmSignMessage(\n connectId: string,\n deviceId: string,\n params: EvmSignMsgParams,\n commonParams?: ICommonCallParams\n ) {\n return this.callChain<EvmSignature>(\n connectId,\n deviceId,\n 'evm',\n 'evmSignMessage',\n params,\n commonParams\n );\n }\n\n evmSignTypedData(\n connectId: string,\n deviceId: string,\n params: EvmSignTypedDataParams,\n commonParams?: ICommonCallParams\n ) {\n return this.callChain<EvmSignature>(\n connectId,\n deviceId,\n 'evm',\n 'evmSignTypedData',\n params,\n commonParams\n );\n }\n\n // ---------------------------------------------------------------------------\n // BTC chain methods\n // ---------------------------------------------------------------------------\n\n btcGetAddress(\n connectId: string,\n deviceId: string,\n params: BtcGetAddressParams,\n commonParams?: ICommonCallParams\n ) {\n return this.callChain<BtcAddress>(\n connectId,\n deviceId,\n 'btc',\n 'btcGetAddress',\n params,\n commonParams\n );\n }\n\n btcGetPublicKey(\n connectId: string,\n deviceId: string,\n params: BtcGetPublicKeyParams,\n commonParams?: ICommonCallParams\n ) {\n return this.callChain<BtcPublicKey>(\n connectId,\n deviceId,\n 'btc',\n 'btcGetPublicKey',\n params,\n commonParams\n );\n }\n\n btcSignTransaction(\n connectId: string,\n deviceId: string,\n params: BtcSignTxParams,\n commonParams?: ICommonCallParams\n ) {\n return this.callChain<BtcSignedTx>(\n connectId,\n deviceId,\n 'btc',\n 'btcSignTransaction',\n params,\n commonParams\n );\n }\n\n btcSignPsbt(\n connectId: string,\n deviceId: string,\n params: BtcSignPsbtParams,\n commonParams?: ICommonCallParams\n ) {\n return this.callChain<BtcSignedPsbt>(\n connectId,\n deviceId,\n 'btc',\n 'btcSignPsbt',\n params,\n commonParams\n );\n }\n\n btcSignMessage(\n connectId: string,\n deviceId: string,\n params: BtcSignMsgParams,\n commonParams?: ICommonCallParams\n ) {\n return this.callChain<BtcSignature>(\n connectId,\n deviceId,\n 'btc',\n 'btcSignMessage',\n params,\n commonParams\n );\n }\n\n btcGetMasterFingerprint(connectId: string, deviceId: string, commonParams?: ICommonCallParams) {\n return this.callChain<{ masterFingerprint: string }>(\n connectId,\n deviceId,\n 'btc',\n 'btcGetMasterFingerprint',\n {},\n commonParams\n );\n }\n\n // ---------------------------------------------------------------------------\n // SOL chain methods\n // ---------------------------------------------------------------------------\n\n solGetAddress(\n connectId: string,\n deviceId: string,\n params: SolGetAddressParams,\n commonParams?: ICommonCallParams\n ) {\n return this.callChain<SolAddress>(\n connectId,\n deviceId,\n 'sol',\n 'solGetAddress',\n params,\n commonParams\n );\n }\n\n solSignTransaction(\n connectId: string,\n deviceId: string,\n params: SolSignTxParams,\n commonParams?: ICommonCallParams\n ) {\n return this.callChain<SolSignedTx>(\n connectId,\n deviceId,\n 'sol',\n 'solSignTransaction',\n params,\n commonParams\n );\n }\n\n solSignMessage(\n connectId: string,\n deviceId: string,\n params: SolSignMsgParams,\n commonParams?: ICommonCallParams\n ) {\n return this.callChain<SolSignature>(\n connectId,\n deviceId,\n 'sol',\n 'solSignMessage',\n params,\n commonParams\n );\n }\n\n // ---------------------------------------------------------------------------\n // TRON chain methods\n // ---------------------------------------------------------------------------\n\n tronGetAddress(\n connectId: string,\n deviceId: string,\n params: TronGetAddressParams,\n commonParams?: ICommonCallParams\n ) {\n return this.callChain<TronAddress>(\n connectId,\n deviceId,\n 'tron',\n 'tronGetAddress',\n params,\n commonParams\n );\n }\n\n tronSignTransaction(\n connectId: string,\n deviceId: string,\n params: TronSignTxParams,\n commonParams?: ICommonCallParams\n ) {\n return this.callChain<TronSignedTx>(\n connectId,\n deviceId,\n 'tron',\n 'tronSignTransaction',\n params,\n commonParams\n );\n }\n\n tronSignMessage(\n connectId: string,\n deviceId: string,\n params: TronSignMsgParams,\n commonParams?: ICommonCallParams\n ) {\n return this.callChain<TronSignature>(\n connectId,\n deviceId,\n 'tron',\n 'tronSignMessage',\n params,\n commonParams\n );\n }\n\n // ---------------------------------------------------------------------------\n // App management — OS-level Ledger app install / list. Bypasses fingerprint\n // and chain-handler dispatch; installApp progress is forwarded to the adapter\n // emitter via 'ui-event' AppInstallProgress events.\n // ---------------------------------------------------------------------------\n\n async installApp(connectId: string, appName: string): Promise<Response<void>> {\n try {\n // Progress is emitted from the connector via a 'ui-event'\n // AppInstallProgress variant (see uiEventForwarder); no callback is\n // passed here so installApp params stay fully serializable across\n // IHardwareBridge.\n await this.connectorCall(connectId, 'installApp', { appName });\n return success(undefined);\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async listInstalledApps(connectId: string): Promise<Response<AppMetadata[]>> {\n try {\n const result = await this.connectorCall(connectId, 'listInstalledApps', {});\n return success(result as AppMetadata[]);\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n // Offline app-presence + unlock probe. No manager-api catalog (unlike listInstalledApps).\n async listInstalledNames(connectId: string): Promise<Response<string[]>> {\n try {\n const result = await this.connectorCall(connectId, 'listInstalledNames', {});\n return success(result as string[]);\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async listAvailableApps(connectId: string): Promise<Response<AppMetadata[]>> {\n try {\n const result = await this.connectorCall(connectId, 'listAvailableApps', {});\n return success(result as AppMetadata[]);\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async getLedgerFirmwareVersion(connectId: string): Promise<Response<FirmwareVersion>> {\n try {\n const result = await this.connectorCall(connectId, 'getFirmwareVersion', {});\n return success(result as FirmwareVersion);\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async getLedgerDeviceInfo(connectId: string): Promise<Response<LedgerDeviceInfo>> {\n try {\n const result = await this.connectorCall(connectId, 'getDeviceInfo', {});\n return success(result as LedgerDeviceInfo);\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Events\n // ---------------------------------------------------------------------------\n\n on<K extends keyof HardwareEventMap>(\n event: K,\n listener: (event: HardwareEventMap[K]) => void\n ): void;\n\n on(event: string, listener: DeviceEventListener): void;\n\n on(event: string, listener: (event: HardwareEvent) => void): void {\n this.emitter.on(event, listener);\n }\n\n off<K extends keyof HardwareEventMap>(\n event: K,\n listener: (event: HardwareEventMap[K]) => void\n ): void;\n\n off(event: string, listener: DeviceEventListener): void;\n\n off(event: string, listener: (event: HardwareEvent) => void): void {\n this.emitter.off(event, listener);\n }\n\n cancel(connectId?: string): void {\n const userAbortReason = Object.assign(new Error('User aborted operation'), {\n code: HardwareErrorCode.UserAborted,\n _tag: ERROR_TAG.UserAborted,\n });\n\n // Hermes/RN polyfills don't always populate signal.reason from\n // abortController.abort(reason). Cache the reason here so _abortable\n // can fall back to it. Cleared after a short window so a stale reason\n // can't taint an unrelated abort later.\n this._lastCancelReason = userAbortReason;\n setTimeout(() => {\n if (this._lastCancelReason === userAbortReason) {\n this._lastCancelReason = undefined;\n }\n }, 2000);\n\n this._uiRegistry.cancel();\n\n // No-connectId path collateral-cancels concurrent silent jobs (known\n // limitation; needs per-job foreground flag to fix).\n if (connectId) {\n this._jobQueue.cancelActiveAndPending(connectId, userAbortReason);\n } else {\n this._jobQueue.cancelActiveAndPending(undefined, userAbortReason);\n }\n\n if (connectId) {\n const sessionId = this._sessions.get(connectId) ?? connectId;\n void this.connector.cancel(sessionId);\n } else {\n for (const sid of this._sessions.values()) void this.connector.cancel(sid);\n }\n\n // Snapshot guard: only abort if connect is actually in flight (avoids\n // hitting a NEW controller from a restart between resolve and re-entry).\n if (this._connectingPromise) {\n this._doConnectAbortController?.abort(userAbortReason);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Chain fingerprint\n // ---------------------------------------------------------------------------\n\n async getChainFingerprint(\n connectId: string,\n deviceId: string,\n chain: ChainForFingerprint\n ): Promise<Response<string>> {\n try {\n const fingerprint = await this._computeChainFingerprint(chain, (method, params) =>\n this.connectorCall(connectId, method, params, undefined, deviceId)\n );\n return success(fingerprint);\n } catch (err) {\n debugError('[LedgerAdapter] getChainFingerprint error:', chain, err);\n return this.errorToFailure(err);\n }\n }\n\n /**\n * Verify fingerprint using an existing sessionId directly.\n * Safe to call inside connectorCall without causing queue deadlock.\n */\n private async _verifyDeviceFingerprintWithSession(\n sessionId: string,\n deviceId: string,\n chain: ChainForFingerprint\n ): Promise<IFingerprintVerifyResult> {\n if (!deviceId) return { success: true };\n\n try {\n const fingerprint = await this._computeChainFingerprint(chain, (method, params) =>\n this._callConnector(sessionId, method, params)\n );\n if (fingerprint === deviceId) {\n return { success: true };\n }\n return { success: false, expected: deviceId, actual: fingerprint };\n } catch (err) {\n const mapped = mapLedgerError(err);\n if (\n mapped.code === HardwareErrorCode.WrongApp ||\n mapped.code === HardwareErrorCode.DeviceLocked\n ) {\n return { success: true };\n }\n throw err;\n }\n }\n\n /**\n * Compute the chain fingerprint via a caller-supplied call strategy.\n *\n * Chains with a native device-side identity primitive (BTC → BIP32 master\n * fingerprint) short-circuit at the top and return it verbatim, so the value\n * stays reusable for higher-level use (BIP380 descriptors, PSBT signing).\n *\n * All other chains derive a fixed-path address and run it through\n * `deriveDeviceFingerprint` to produce an opaque seed identifier.\n *\n * The two callers (`getChainFingerprint` / `_verifyDeviceFingerprintWithSession`)\n * differ only in the underlying call mechanism, which is injected as `callMethod`\n * to avoid queue deadlocks when running inside `connectorCall`.\n */\n private async _computeChainFingerprint(\n chain: ChainForFingerprint,\n callMethod: (method: string, params: unknown) => Promise<unknown>\n ): Promise<string> {\n // BTC: dedicated device call returns the BIP32 master fingerprint already\n // in the canonical 8-hex form — no further hashing.\n if (chain === 'btc') {\n const result = (await callMethod('btcGetMasterFingerprint', {})) as {\n masterFingerprint: string;\n };\n return result.masterFingerprint;\n }\n\n const path = CHAIN_FINGERPRINT_PATHS[chain];\n let address: string;\n if (chain === 'evm') {\n // Lowercase per deriveDeviceFingerprint's canonical-form contract.\n address = (\n (await callMethod('evmGetAddress', { path, showOnDevice: false })) as {\n address: string;\n }\n ).address.toLowerCase();\n } else if (chain === 'sol') {\n address = (\n (await callMethod('solGetAddress', { path, showOnDevice: false })) as {\n address: string;\n }\n ).address;\n } else if (chain === 'tron') {\n address = (\n (await callMethod('tronGetAddress', { path, showOnDevice: false })) as {\n address: string;\n }\n ).address;\n } else {\n throw new Error(`Unsupported chain for fingerprint: ${chain as string}`);\n }\n\n return deriveDeviceFingerprint(address);\n }\n\n // ---------------------------------------------------------------------------\n // Private helpers\n // ---------------------------------------------------------------------------\n\n /**\n * Ensure at least one device is connected and return a valid connectId.\n *\n * - If a session already exists for the given connectId, reuse it.\n * - If ANY session exists (Ledger IDs are ephemeral), reuse it.\n * - Otherwise: search → exactly 1 USB device auto-connects; multiple or none throws.\n */\n // Mutex for ensureConnected — prevents concurrent calls from establishing duplicate connections\n private _connectingPromise: Promise<string> | null = null;\n\n // Ledger WebUSB won't expose a locked device, so we can't auto-detect unlock.\n // The user must press Confirm after unlocking, which triggers a search retry.\n // If `signal` is provided, an abort cancels the pending UI request so the\n // registry slot is released and a stale RECEIVE_DEVICE_CONNECT won't land in\n // a future request.\n private async _waitForDeviceConnect(signal?: AbortSignal): Promise<void> {\n if (signal?.aborted) {\n LedgerAdapter._throwIfAborted(signal);\n }\n\n // Register the wait FIRST. A synchronous consumer that calls `uiResponse`\n // inside the emit handler would otherwise resolve before the registry\n // slot exists, and the response would be silently dropped (see\n // UiRequestRegistry.resolve early-return on missing entry).\n const waitPromise = this._uiRegistry.wait<{ confirmed: boolean }>(\n UI_REQUEST.REQUEST_DEVICE_CONNECT\n );\n\n this.emitter.emit(UI_REQUEST.REQUEST_DEVICE_CONNECT, {\n type: UI_REQUEST.REQUEST_DEVICE_CONNECT,\n payload: {\n vendor: 'ledger',\n reason: 'device-not-found',\n message: 'Please connect and unlock your Ledger device',\n },\n });\n\n let payload: { confirmed: boolean } | undefined;\n try {\n if (signal) {\n const onAbort = () => {\n this._uiRegistry.cancel(UI_REQUEST.REQUEST_DEVICE_CONNECT);\n };\n signal.addEventListener('abort', onAbort, { once: true });\n try {\n payload = await waitPromise;\n } finally {\n signal.removeEventListener('abort', onAbort);\n }\n } else {\n payload = await waitPromise;\n }\n } catch (err) {\n // External cancel (signal abort / jobQueue cancel) — app's atom may\n // still be set, so signal it to drop the dialog.\n this.emitter.emit(UI_REQUEST.CLOSE_UI_WINDOW, {\n type: UI_REQUEST.CLOSE_UI_WINDOW,\n payload: {},\n });\n // Re-tag as UserAborted so upstream classifiers stop the batch.\n throw Object.assign(new Error('User cancelled Ledger connection'), {\n _tag: ERROR_TAG.UserAborted,\n code: HardwareErrorCode.UserAborted,\n cause: err,\n });\n }\n\n if (!payload?.confirmed) {\n throw Object.assign(new Error('User cancelled Ledger connection'), {\n _tag: ERROR_TAG.UserAborted,\n code: HardwareErrorCode.UserAborted,\n });\n }\n\n // BLE peripheral needs a moment to settle after user unlocks the device.\n // Without this delay, the immediate searchDevices() following Confirm\n // often returns 0, forcing another loop iteration.\n await new Promise<void>(resolve => {\n setTimeout(resolve, 800);\n });\n }\n\n /**\n * Decide whether a BTC pubkey call needs `showOnDevice=true` because of\n * the BTC App's account-index policy, asking the user once per session.\n *\n * Returns the params to pass through (with `showOnDevice` possibly\n * promoted), or `null` if the user declined.\n */\n private async _gateBtcHighIndex(\n params: BtcGetPublicKeyParams\n ): Promise<BtcGetPublicKeyParams | null> {\n const accountIndex = btcAccountIndexFromPath(params.path);\n if (params.showOnDevice) return params;\n if (accountIndex === null || accountIndex < BTC_HIGH_INDEX_THRESHOLD) {\n return params;\n }\n if (this._btcHighIndexConfirmedThisSession) {\n return { ...params, showOnDevice: true };\n }\n const confirmed = await this._waitForBtcHighIndexConfirm(params.path, accountIndex);\n if (!confirmed) return null;\n this._btcHighIndexConfirmedThisSession = true;\n return { ...params, showOnDevice: true };\n }\n\n private async _waitForBtcHighIndexConfirm(path: string, accountIndex: number): Promise<boolean> {\n // Register the wait FIRST. A synchronous consumer that calls `uiResponse`\n // inside the emit handler would otherwise resolve before the registry\n // slot exists, and the response would be silently dropped (see\n // UiRequestRegistry.resolve early-return on missing entry).\n const waitPromise = this._uiRegistry.wait<{ confirmed: boolean }>(\n UI_REQUEST.REQUEST_BTC_HIGH_INDEX_CONFIRM\n );\n\n this.emitter.emit(UI_REQUEST.REQUEST_BTC_HIGH_INDEX_CONFIRM, {\n type: UI_REQUEST.REQUEST_BTC_HIGH_INDEX_CONFIRM,\n payload: {\n vendor: 'ledger',\n path,\n accountIndex,\n },\n });\n\n try {\n const payload = await waitPromise;\n return !!payload?.confirmed;\n } catch (err) {\n this.emitter.emit(UI_REQUEST.CLOSE_UI_WINDOW, {\n type: UI_REQUEST.CLOSE_UI_WINDOW,\n payload: {},\n });\n return false;\n }\n }\n\n // Ask the user whether to install a missing app (autoInstallApp flow).\n // Same register-then-emit ordering as the BTC high-index gate.\n private async _waitForInstallAppConfirm(appName: string): Promise<boolean> {\n const waitPromise = this._uiRegistry.wait<{ confirmed: boolean }>(\n UI_REQUEST.REQUEST_INSTALL_APP\n );\n\n this.emitter.emit(UI_REQUEST.REQUEST_INSTALL_APP, {\n type: UI_REQUEST.REQUEST_INSTALL_APP,\n payload: { vendor: 'ledger', appName },\n });\n\n try {\n const payload = await waitPromise;\n return !!payload?.confirmed;\n } catch (err) {\n this.emitter.emit(UI_REQUEST.CLOSE_UI_WINDOW, {\n type: UI_REQUEST.CLOSE_UI_WINDOW,\n payload: {},\n });\n return false;\n }\n }\n\n // Layer 1 entry. Caller signal only races the outer awaiter; the shared\n // `_doConnect` runs under its own internal controller so caller A's cancel\n // doesn't kill caller B's await.\n private async ensureConnected(\n connectId: string | undefined,\n signal: AbortSignal,\n allowUsbEphemeralFallback = false\n ): Promise<string> {\n if (signal.aborted) LedgerAdapter._throwIfAborted(signal);\n\n if (isLedgerBleConnectionType(this.connector.connectionType) && !connectId) {\n throw Object.assign(new Error('Ledger BLE connectId is required.'), {\n code: HardwareErrorCode.DeviceNotFound,\n });\n }\n\n if (connectId && this._sessions.has(connectId)) return connectId;\n // Ambient fallback only when the caller gave no target. On an explicit\n // connectId miss, re-resolve THAT device via _doConnect — never route to\n // the first session entry (a stale entry for B once made A's calls hit B).\n if (!connectId && this._sessions.size > 0) {\n // Fail loud rather than route to a wrong device; connectDevice evicts\n // first, so size>1 here should be impossible.\n if (!isLedgerBleConnectionType(this.connector.connectionType) && this._sessions.size > 1) {\n throw Object.assign(\n new Error(\n 'Ledger USB session invariant violated: more than one session is active. Please reconnect the device.'\n ),\n { code: HardwareErrorCode.DeviceOneDeviceOnly }\n );\n }\n return this._sessions.keys().next().value as string;\n }\n\n if (!this._connectingPromise) {\n this._doConnectAbortController = new AbortController();\n const innerSignal = this._doConnectAbortController.signal;\n this._connectingPromise = (async () => {\n try {\n return await this._doConnect(innerSignal, connectId, allowUsbEphemeralFallback);\n } finally {\n this._connectingPromise = null;\n this._doConnectAbortController = null;\n }\n })();\n }\n\n return this._abortable(signal, this._connectingPromise);\n }\n\n // Layer 1 main loop — the ONLY place in SDK that emits unlock dialog.\n // Bounded by MAX_DOCONNECT_CONFIRMS — after N Confirms with no progress,\n // throw DeviceNotFound so the user is kicked out of the loop.\n private async _doConnect(\n internalSignal: AbortSignal,\n targetConnectId?: string,\n allowUsbEphemeralFallback = false\n ): Promise<string> {\n if (isLedgerBleConnectionType(this.connector.connectionType) && targetConnectId) {\n try {\n return await this._connectDeviceOrThrow(targetConnectId);\n } catch (err) {\n if (\n !isDeviceLockedError(err) &&\n !isDeviceNotAdvertisingError(err) &&\n !isDeviceDisconnectedError(err)\n ) {\n throw err;\n }\n this._discoveredDevices.delete(targetConnectId);\n if (isDeviceDisconnectedError(err)) {\n try {\n this.connector.reset?.();\n } catch {\n // best-effort\n }\n }\n }\n }\n\n let confirms = 0;\n while (!internalSignal.aborted) {\n // Tell consumers we're actively scanning. Re-emitted at every iteration\n // so the toast comes back after `_waitForDeviceConnect` closes its\n // dialog — the dialog overrides the searching toast while open, and\n // the next round needs an explicit signal to bring it back.\n this.emitter.emit('ui-event', {\n type: EConnectorInteraction.Searching,\n payload: { sessionId: '' },\n });\n let devices = await this.searchDevices();\n\n // First scan empty? Retry — BLE state can be flaky right after a\n // PairingRefused / Disconnect / fresh app restart, and ble-plx scans\n // sometimes miss a device that's actually advertising. Worth a few\n // extra seconds before bothering the user with a dialog.\n if (devices.length === 0) {\n for (let i = 0; i < 3 && !internalSignal.aborted; i += 1) {\n await new Promise<void>(resolve => {\n setTimeout(resolve, 1000);\n });\n devices = await this.searchDevices();\n if (devices.length > 0) break;\n }\n }\n\n if (devices.length > 0) {\n try {\n return await this._connectFirstOrSelect(\n devices,\n targetConnectId,\n allowUsbEphemeralFallback\n );\n } catch (err) {\n // PairingFailure / DeviceMismatch / unclassified → throw out, no\n // Layer 1 retry. PairingRefused = user declined system pair prompt\n // / didn't confirm on device — edge case, let upstream surface it.\n // Locked / NotAdvertising / Disconnected stay as recoverable since\n // they often clear themselves between attempts.\n if (\n !isDeviceLockedError(err) &&\n !isDeviceNotAdvertisingError(err) &&\n !isDeviceDisconnectedError(err)\n ) {\n throw err;\n }\n this._discoveredDevices.clear();\n if (isDeviceDisconnectedError(err)) {\n try {\n this.connector.reset?.();\n } catch {\n // best-effort\n }\n }\n }\n }\n\n if (confirms >= LedgerAdapter.MAX_DOCONNECT_CONFIRMS) {\n throw Object.assign(\n new Error(\n 'Device not connected after multiple attempts. Please ensure your Ledger is awake, unlocked, and in range, then try again.'\n ),\n { code: HardwareErrorCode.DeviceNotFound }\n );\n }\n\n await this._waitForDeviceConnect(internalSignal);\n confirms += 1;\n }\n LedgerAdapter._throwIfAborted(internalSignal);\n // Unreachable — _throwIfAborted always throws when aborted.\n throw new Error('_doConnect aborted');\n }\n\n private async _connectFirstOrSelect(\n devices: DeviceInfo[],\n targetConnectId?: string,\n allowUsbEphemeralFallback = false\n ): Promise<string> {\n if (targetConnectId) {\n const target = devices.find(\n d => d.connectId === targetConnectId || d.deviceId === targetConnectId\n );\n if (target) {\n return this._connectDeviceOrThrow(target.connectId);\n }\n\n // Decision: a stale USB target + fresh search returning exactly one\n // Ledger is not proof that the sole Ledger is the original device. It\n // might be A after a replug (safe to recover), or B after A was unplugged\n // (wrong-device risk).\n //\n // We only take this recovery path when the business call supplied a\n // stable wallet fingerprint (`deviceId`) and did not opt out of\n // fingerprint checks. The connection is then provisional: the caller must\n // run `_verifyDeviceFingerprintWithSession` before sending the real APDU.\n // Calls without that identity check fail closed with DeviceNotFound so\n // the host can ask the user to reconnect/select again.\n if (\n !isLedgerBleConnectionType(this.connector.connectionType) &&\n devices.length === 1 &&\n allowUsbEphemeralFallback\n ) {\n debugLog(\n `[LedgerAdapter] target ${targetConnectId} not in fresh enumeration; ` +\n `accepting sole USB device ${devices[0].connectId} for fingerprint-verified recovery`\n );\n return this._connectDeviceOrThrow(devices[0].connectId);\n }\n\n const err = Object.assign(new Error(`Target Ledger unavailable: ${targetConnectId}`), {\n code: HardwareErrorCode.DeviceNotFound,\n }) as Error & { _tag?: string };\n if (isLedgerBleConnectionType(this.connector.connectionType)) {\n err._tag = ERROR_TAG.DeviceNotAdvertising;\n }\n throw err;\n }\n\n if (isLedgerBleConnectionType(this.connector.connectionType)) {\n throw Object.assign(new Error('Ledger BLE connectId is required.'), {\n code: HardwareErrorCode.DeviceNotFound,\n });\n }\n\n // No target + multiple USB devices: refuse to auto-pick by ephemeral\n // connectId (the multi-device drift bug). Caller must specify which device.\n if (devices.length > 1) {\n throw createMultipleUsbLedgerDevicesError();\n }\n\n if (devices.length !== 1) {\n throw Object.assign(new Error('Ledger device not found.'), {\n code: HardwareErrorCode.DeviceNotFound,\n });\n }\n\n return this._connectDeviceOrThrow(devices[0].connectId);\n }\n\n private async _connectDeviceOrThrow(chosenConnectId: string): Promise<string> {\n const result = await this.connectDevice(chosenConnectId);\n if (!result.success) {\n // _tag must survive — _doConnect's catch is _tag-based.\n const payload = result.payload as { error: string; code: number; _tag?: string };\n const rethrow = Object.assign(new Error(payload.error), {\n code: payload.code,\n }) as Error & { _tag?: string };\n if (payload._tag !== undefined) {\n rethrow._tag = payload._tag;\n }\n throw rethrow;\n }\n return chosenConnectId;\n }\n\n /**\n * Call the connector with automatic session resolution and disconnect retry.\n *\n * 1. Resolves a valid connectId via ensureConnected()\n * 2. Looks up sessionId from _sessions\n * 3. Calls connector.call()\n * 4. On disconnect error: clears stale session, re-connects, retries once\n */\n /**\n * Unwrap a `ConnectorCallResult` back into the throw-based control flow this\n * class relies on. On failure, rehydrate a FLAT Error (lifting `params.*`\n * back to own-properties) so the downstream recovery predicates\n * (`isStuckAppStateError`, `isDeviceLockedError`, …) and `mapLedgerError`\n * (which read `err._tag` / `err.code` / `err.appName` / `err.originalError`)\n * keep working exactly as before — the Result shape is confined to the\n * connector boundary.\n */\n private _unwrapConnectorResult(result: ConnectorCallResult): unknown {\n if (result.success) return result.payload;\n throw rehydrateConnectorError(result.error);\n }\n\n /**\n * `connector.call` + result unwrap, optionally raced against an abort\n * signal. Returns the call payload or throws the rehydrated error. All\n * `this.connector.call` usage goes through here so the Result→throw seam\n * lives in one place.\n */\n private async _callConnector(\n sessionId: string,\n method: string,\n params: unknown,\n signal?: AbortSignal\n ): Promise<unknown> {\n const promise = this.connector.call(sessionId, method, params);\n const result = signal ? await this._abortable(signal, promise) : await promise;\n return this._unwrapConnectorResult(result);\n }\n\n private async connectorCall(\n connectId: string,\n method: string,\n params: unknown,\n fingerprint?: ConnectorCallFingerprint,\n permissionDeviceId?: string,\n commonParams?: ICommonCallParams,\n installContext?: LedgerInstallAppContext\n ): Promise<unknown> {\n // [REQ] / [RES] are the canonical request/response trace for any operation\n // that hits the device — chain methods, installApp, list*, firmware, etc.\n // Diagnostic / recovery debugLog lines below are NOT a duplicate: they log\n // what the SDK decides to do about an error, not the response itself.\n debugLog('[LedgerAdapter][REQ]', { method, connectId: connectId || '(empty)', params });\n\n // Queue is global serial; deviceId is just a label for inspection / cancellation.\n const queueKey = connectId || '__ledger_default__';\n\n try {\n const result = await this._jobQueue.enqueue(\n queueKey,\n async signal =>\n this._runConnectorCall(\n connectId,\n method,\n params,\n signal,\n fingerprint,\n permissionDeviceId,\n commonParams,\n installContext\n ),\n {\n label: method,\n rejectIfBusy: true,\n busyError: LedgerAdapter._createDeviceBusyError(method),\n }\n );\n debugLog('[LedgerAdapter][RES]', { method, success: true, payload: result });\n return result;\n } catch (err) {\n const e = err as Record<string, unknown> | null | undefined;\n debugLog('[LedgerAdapter][RES]', {\n method,\n success: false,\n error: {\n message: e?.message,\n _tag: e?._tag,\n code: e?.code ?? e?.errorCode,\n },\n });\n throw err;\n }\n }\n\n /**\n * Race a promise against an abort signal. On abort, rejects with\n * signal.reason → instance _lastCancelReason → generic Error('Aborted').\n */\n private _abortable<T>(signal: AbortSignal, promise: Promise<T>): Promise<T> {\n const getAbortReason = () =>\n (signal as AbortSignal & { reason?: unknown }).reason ??\n this._lastCancelReason ??\n new Error('Aborted');\n\n if (signal.aborted) {\n return Promise.reject(getAbortReason());\n }\n return new Promise<T>((resolve, reject) => {\n const onAbort = () => {\n reject(getAbortReason());\n };\n signal.addEventListener('abort', onAbort, { once: true });\n promise.then(\n value => {\n signal.removeEventListener('abort', onAbort);\n resolve(value);\n },\n err => {\n signal.removeEventListener('abort', onAbort);\n reject(err);\n }\n );\n });\n }\n\n /** Throw an AbortError if signal is already aborted. */\n private static _throwIfAborted(signal: AbortSignal): void {\n if (signal.aborted) {\n throw (signal as AbortSignal & { reason?: unknown }).reason ?? new Error('Aborted');\n }\n }\n\n /** Actual work done under the job queue — connection, fingerprint, call, and recovery. */\n private async _runConnectorCall(\n connectId: string,\n method: string,\n params: unknown,\n signal: AbortSignal,\n fingerprint?: ConnectorCallFingerprint,\n permissionDeviceId?: string,\n commonParams?: ICommonCallParams,\n installContext?: LedgerInstallAppContext\n ): Promise<unknown> {\n LedgerAdapter._throwIfAborted(signal);\n await this._ensureDevicePermission(\n connectId,\n permissionDeviceId ?? fingerprint?.deviceId,\n signal\n );\n LedgerAdapter._throwIfAborted(signal);\n let effectiveParams = params;\n if (method === 'btcGetPublicKey') {\n const gatedParams = await this._gateBtcHighIndex(params as BtcGetPublicKeyParams);\n if (gatedParams === null) {\n throw Object.assign(new Error('User cancelled BTC high-index confirmation'), {\n _tag: ERROR_TAG.UserAborted,\n code: HardwareErrorCode.UserAborted,\n });\n }\n effectiveParams = gatedParams;\n }\n\n const allowUsbEphemeralFallback = !!fingerprint?.deviceId && !fingerprint.skipFingerprint;\n\n // Wrap ensureConnected in _abortable so an abort during device discovery /\n // user-connect UI wait rejects this caller immediately. The underlying\n // _doConnect / _connectingPromise is shared across callers and continues\n // running — other concurrent callers aren't affected.\n const resolvedConnectId = await this.ensureConnected(\n connectId,\n signal,\n allowUsbEphemeralFallback\n );\n const sessionId = this._sessions.get(resolvedConnectId);\n if (!sessionId) {\n throw Object.assign(new Error('Auto-connect succeeded but no session found'), {\n _tag: ERROR_TAG.DeviceSessionNotFound,\n });\n }\n\n // Fingerprint verification inside the session — atomic with the actual call\n try {\n // Fingerprint verification lives inside the same try/catch as the main\n // call so that transport-level errors raised by `_computeChainFingerprint`\n // (e.g. \"Device communication interrupted\") flow through the recovery\n // path below — clearing session + resetting connector. Without this,\n // a stuck DMK transport during fingerprint check leaks the dead\n // session to subsequent retries (they keep using the same broken\n // sessionId until the user replugs).\n if (fingerprint && !fingerprint.skipFingerprint && fingerprint.deviceId) {\n const fp = await this._abortable(\n signal,\n this._verifyDeviceFingerprintWithSession(\n sessionId,\n fingerprint.deviceId,\n fingerprint.chain\n )\n );\n if (!fp.success) {\n throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {\n code: HardwareErrorCode.DeviceMismatch,\n });\n }\n }\n return await this._callConnector(sessionId, method, effectiveParams, signal);\n } catch (err) {\n // If the abort fired, surface it directly — skip recovery paths.\n if (signal.aborted) throw err;\n const errObj = err as Record<string, unknown> | null | undefined;\n debugLog('[LedgerAdapter] connectorCall error:', method, {\n message: errObj?.message,\n _tag: errObj?._tag,\n errorCode: errObj?.errorCode,\n statusCode: errObj?.statusCode,\n isDisconnected: isDeviceDisconnectedError(err),\n isLocked: isDeviceLockedError(err),\n isNotAdvertising: isDeviceNotAdvertisingError(err),\n isStuckApp: isStuckAppStateError(err),\n });\n\n // Auto-install: required app missing + caller opted in via commonParams.\n // Ask the user, install (DMK returns to dashboard then installs, streaming\n // AppInstallProgress ui-events), then retry the original op once. The\n // install runs as a direct connector call within THIS queue slot — going\n // through the public installApp/connectorCall would re-enter the serial\n // job queue and reject as busy.\n const autoInstallApp = commonParams?.autoInstallApp ?? this._defaultAutoInstallApp;\n const isAppMissing =\n isAppNotInstalledError(err) ||\n (err as { code?: number })?.code === HardwareErrorCode.AppNotInstalled;\n if (autoInstallApp && isAppMissing) {\n if (installContext?.deviceOutOfMemoryError) {\n throw installContext.deviceOutOfMemoryError;\n }\n const appName = (err as { appName?: string })?.appName ?? mapLedgerError(err).appName;\n if (appName) {\n // Loop guard: if installApp already resolved once this bundle but\n // the app is STILL missing, DMK is lying about success. Don't\n // re-prompt — surface a clear failure so the bundle moves on.\n if (installContext?.installAttemptedAppNames?.has(appName)) {\n throw createHwkError({\n code: HardwareErrorCode.AppNotInstalled,\n message: `${appName} install reported success but the app is still missing on device`,\n _tag: ERROR_TAG.AppInstallVerifyFailed,\n appName,\n });\n }\n const confirmed = await this._waitForInstallAppConfirm(appName);\n if (!confirmed) {\n throw createHwkError({\n code: HardwareErrorCode.UserAborted,\n message: `User declined to install ${appName}`,\n _tag: ERROR_TAG.UserAborted,\n appName,\n });\n }\n // Emit progress 0 immediately so the confirm dialog morphs into the\n // \"installing\" view with no blank gap — DMK's setup (go-to-dashboard,\n // metadata, build plan, secure channel) can take several seconds\n // before the first real progress arrives.\n this.emitter.emit('ui-event', {\n type: EConnectorInteraction.AppInstallProgress,\n payload: { connectId: resolvedConnectId, appName, progress: 0 },\n });\n try {\n await this._callConnector(sessionId, 'installApp', { appName }, signal);\n } catch (installErr) {\n if (mapLedgerError(installErr).code === HardwareErrorCode.DeviceOutOfMemory) {\n if (installContext) {\n installContext.deviceOutOfMemoryError = installErr as Error;\n }\n }\n throw installErr;\n }\n if (installContext) {\n installContext.installAttemptedAppNames =\n installContext.installAttemptedAppNames ?? new Set();\n installContext.installAttemptedAppNames.add(appName);\n }\n // Close the install UI before retrying so the retried operation's own\n // device prompts (e.g. confirm-on-device) render normally instead of\n // being absorbed by the install dialog.\n this.emitter.emit(UI_REQUEST.CLOSE_UI_WINDOW, {\n type: UI_REQUEST.CLOSE_UI_WINDOW,\n payload: {},\n });\n return await this._runConnectorCall(\n resolvedConnectId,\n method,\n effectiveParams,\n signal,\n fingerprint,\n permissionDeviceId,\n commonParams,\n installContext\n );\n }\n }\n\n // Stuck DMK slot — reset transport, wait briefly, retry ONCE.\n // Trigger: Stax CloseApp→OpenApp race returns APDU 6901 before the\n // user can react. A short pause lets the device finish its transition;\n // on persistent 6901 the user really does need to act, so surface it.\n if (isStuckAppStateError(err)) {\n try {\n this._sessions.delete(resolvedConnectId);\n this._discoveredDevices.delete(resolvedConnectId);\n this.connector.reset?.();\n } catch {\n // best-effort reset — fall through to retry\n }\n debugLog(\n '[LedgerAdapter] stuck-app retry: method=',\n method,\n 'delayMs=',\n LedgerAdapter.STUCK_APP_RETRY_DELAY_MS,\n '_tag=',\n (err as Record<string, unknown> | null | undefined)?._tag\n );\n try {\n const retryResult = await this._retryAfterStuckApp(\n resolvedConnectId,\n method,\n effectiveParams,\n signal,\n err,\n fingerprint\n );\n debugLog('[LedgerAdapter] stuck-app retry succeeded: method=', method);\n return retryResult;\n } catch (retryErr) {\n if (signal.aborted) throw retryErr;\n // Second stuck-app hit → genuinely needs user action; surface\n // the original error so callers see a consistent _tag.\n if (isStuckAppStateError(retryErr)) {\n debugLog('[LedgerAdapter] stuck-app retry exhausted (2nd 6901): method=', method);\n throw err;\n }\n debugLog(\n '[LedgerAdapter] stuck-app retry threw non-stuck error: method=',\n method,\n 'retryErrTag=',\n (retryErr as Record<string, unknown> | null | undefined)?._tag\n );\n throw retryErr;\n }\n }\n\n // Connection-class error → Layer 2 retry (bounded budget).\n // PairingFailure intentionally NOT retried — user declined the OS\n // pair prompt / didn't confirm on device, retrying makes no sense.\n if (\n isDeviceLockedError(err) ||\n isDeviceNotAdvertisingError(err) ||\n isDeviceDisconnectedError(err)\n ) {\n let lastErr: unknown = err;\n for (let attempt = 0; attempt < LedgerAdapter.MAX_BUSINESS_RETRY_BUDGET; attempt += 1) {\n if (signal.aborted) throw lastErr;\n\n try {\n this._sessions.delete(resolvedConnectId);\n this._discoveredDevices.delete(resolvedConnectId);\n\n // Disconnected: DMK transport may retain stale session. Drop\n // DMK so ensureConnected rebuilds from scratch. Locked /\n // NotAdvertising don't need this — DMK side is clean.\n if (isDeviceDisconnectedError(lastErr)) {\n try {\n this.connector.reset?.();\n } catch {\n // best-effort\n }\n }\n // ensureConnected → _doConnect handles \"device not found\" UI\n // request (search returns 0). DMK's unlock-device propagates\n // as a ui-event toast and self-recovers, so DeviceLocked from\n // DMK never reaches Layer 2. The only DeviceLocked here is\n // from APDU 0x5515 (rare hardware-direct), and _doConnect's\n // dialog still covers it via the same UI request.\n\n // Preserve connectId across retry to prevent multi-device drift.\n // USB replug fallback is allowed only when this call will verify\n // the device fingerprint before sending the business APDU.\n const reConnectId = await this.ensureConnected(\n resolvedConnectId,\n signal,\n allowUsbEphemeralFallback\n );\n const reSessionId = this._sessions.get(reConnectId);\n if (!reSessionId) throw lastErr;\n\n // Re-verify fingerprint — Layer 1 may have picked a different\n // physical device (multi-Ledger rig).\n if (fingerprint && !fingerprint.skipFingerprint && fingerprint.deviceId) {\n const fp = await this._abortable(\n signal,\n this._verifyDeviceFingerprintWithSession(\n reSessionId,\n fingerprint.deviceId,\n fingerprint.chain\n )\n );\n if (!fp.success) {\n throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {\n code: HardwareErrorCode.DeviceMismatch,\n });\n }\n }\n\n return await this._callConnector(reSessionId, method, effectiveParams, signal);\n } catch (retryErr) {\n if (signal.aborted) throw retryErr;\n lastErr = retryErr;\n const canRetry =\n attempt < LedgerAdapter.MAX_BUSINESS_RETRY_BUDGET - 1 &&\n (isDeviceLockedError(retryErr) ||\n isDeviceNotAdvertisingError(retryErr) ||\n isDeviceDisconnectedError(retryErr));\n if (!canRetry) {\n throw retryErr;\n }\n }\n }\n // Budget exhausted — surface last seen error to caller.\n throw lastErr;\n }\n\n if (isTimeoutError(err)) {\n debugLog('[LedgerAdapter] timeout, retrying with fresh connection...');\n this._discoveredDevices.delete(resolvedConnectId);\n return this._retryWithFreshConnection(\n resolvedConnectId,\n method,\n effectiveParams,\n signal,\n err,\n fingerprint\n );\n }\n\n // Fail-closed for connection-level errors so batch can't continue on\n // a wedged transport. Reset connector so next caller gets fresh DMK.\n if (isConnectionLevelError(err)) {\n debugLog('[LedgerAdapter] connection-level fail-closed reset');\n this._sessions.delete(resolvedConnectId);\n this._discoveredDevices.delete(resolvedConnectId);\n this.connector.reset();\n const codeNum = (err as { code?: number })?.code;\n throw Object.assign(err as Error, {\n code: codeNum ?? HardwareErrorCode.DeviceDisconnected,\n });\n }\n\n // Business errors (BlindSigning, AppStuck, etc.) propagate untouched.\n throw err;\n }\n }\n\n /**\n * Stuck-app recovery: pause for the device's UI transition, then retry once.\n *\n * Caller has already cleared the session + reset connector. We wait so Stax\n * finishes its post-CloseApp animation, then go through ensureConnected +\n * fingerprint check + call exactly once. Caller decides what to do on a\n * second stuck-app hit.\n */\n private async _retryAfterStuckApp(\n resolvedConnectId: string,\n method: string,\n params: unknown,\n signal: AbortSignal,\n originalErr: unknown,\n fingerprint?: ConnectorCallFingerprint\n ): Promise<unknown> {\n await this._sleepAbortable(LedgerAdapter.STUCK_APP_RETRY_DELAY_MS, signal);\n\n // Preserve connectId across retry (APDU 6901 didn't disconnect, so it's\n // still valid). If a USB replug changed the connectId, recover only when\n // the call has a fingerprint check queued immediately after reconnect.\n const retryConnectId = await this.ensureConnected(\n resolvedConnectId,\n signal,\n !!fingerprint?.deviceId && !fingerprint.skipFingerprint\n );\n const retrySessionId = this._sessions.get(retryConnectId);\n if (!retrySessionId) throw originalErr;\n\n if (fingerprint && !fingerprint.skipFingerprint && fingerprint.deviceId) {\n const fp = await this._abortable(\n signal,\n this._verifyDeviceFingerprintWithSession(\n retrySessionId,\n fingerprint.deviceId,\n fingerprint.chain\n )\n );\n if (!fp.success) {\n throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {\n code: HardwareErrorCode.DeviceMismatch,\n });\n }\n }\n\n return this._callConnector(retrySessionId, method, params, signal);\n }\n\n private _sleepAbortable(ms: number, signal: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal.aborted) {\n reject((signal.reason as Error | undefined) ?? new Error('Aborted'));\n return;\n }\n const timer = setTimeout(() => {\n signal.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n const onAbort = () => {\n clearTimeout(timer);\n reject((signal.reason as Error | undefined) ?? new Error('Aborted'));\n };\n signal.addEventListener('abort', onAbort, { once: true });\n });\n }\n\n /**\n * Clear stale session, reconnect, and retry the call.\n *\n * Timeout recovery starts with a full connector reset. After an APDU\n * timeout, DMK/transport state may still emit malformed responses; retrying\n * on the same DMK can poison the next chain switch.\n */\n private async _retryWithFreshConnection(\n targetConnectId: string,\n method: string,\n params: unknown,\n signal: AbortSignal,\n originalErr: unknown,\n fingerprint?: ConnectorCallFingerprint\n ): Promise<unknown> {\n this.connector.reset();\n this._sessions.clear();\n this._discoveredDevices.clear();\n this._connectingPromise = null;\n\n const allowUsbEphemeralFallback = !!fingerprint?.deviceId && !fingerprint.skipFingerprint;\n const retryConnectId = await this.ensureConnected(\n targetConnectId,\n signal,\n allowUsbEphemeralFallback\n );\n const retrySessionId = this._sessions.get(retryConnectId);\n if (!retrySessionId) {\n throw originalErr;\n }\n try {\n if (fingerprint && !fingerprint.skipFingerprint && fingerprint.deviceId) {\n const fp = await this._abortable(\n signal,\n this._verifyDeviceFingerprintWithSession(\n retrySessionId,\n fingerprint.deviceId,\n fingerprint.chain\n )\n );\n if (!fp.success) {\n throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {\n code: HardwareErrorCode.DeviceMismatch,\n });\n }\n }\n\n return await this._callConnector(retrySessionId, method, params, signal);\n } catch (retryErr) {\n if (signal.aborted) throw retryErr;\n this.connector.reset();\n this._sessions.clear();\n this._discoveredDevices.clear();\n this._connectingPromise = null;\n if (!isDeviceDisconnectedError(retryErr) && !isTimeoutError(retryErr)) {\n throw retryErr;\n }\n debugLog(\n '[LedgerAdapter] fresh-session retry still failed; resetting connector and rebuilding DMK'\n );\n // Full reset: drops _dmk, _deviceManager, _signerManager, ID maps\n // and in-flight cancellers. Next ensureConnected() will rebuild from\n // the ground up via _doConnect → connector.connect → fresh DMK.\n this.connector.reset();\n this._sessions.clear();\n this._discoveredDevices.clear();\n this._connectingPromise = null;\n const finalConnectId = await this.ensureConnected(\n targetConnectId,\n signal,\n allowUsbEphemeralFallback\n );\n const finalSessionId = this._sessions.get(finalConnectId);\n if (!finalSessionId) {\n throw originalErr;\n }\n\n // Re-verify fingerprint after the full reset — `ensureConnected` may have\n // selected a different physical device (e.g. multi-Ledger BLE rig where\n // the original peripheral went out of range). Without this replay,\n // `connector.call` could sign on the wrong device.\n if (fingerprint && !fingerprint.skipFingerprint && fingerprint.deviceId) {\n const fp = await this._abortable(\n signal,\n this._verifyDeviceFingerprintWithSession(\n finalSessionId,\n fingerprint.deviceId,\n fingerprint.chain\n )\n );\n if (!fp.success) {\n throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {\n code: HardwareErrorCode.DeviceMismatch,\n });\n }\n }\n\n return this._callConnector(finalSessionId, method, params, signal);\n }\n }\n\n /**\n * Ensure OS-level device permission (Bluetooth / USB) before proceeding.\n *\n * Emits `REQUEST_DEVICE_PERMISSION` and awaits the consumer's\n * `RECEIVE_DEVICE_PERMISSION` reply (60s budget covers \"probe → system\n * prompt → user tap\" plus a generous margin). If the consumer never wires\n * a handler or never replies, the wait times out and the operation fails\n * fast so scanners/callers don't hang silently.\n *\n * - No connectId (searchDevices): environment-level permission\n * - With connectId (business methods): device-level permission\n */\n private async _ensureDevicePermission(\n connectId?: string,\n deviceId?: string,\n signal?: AbortSignal\n ): Promise<void> {\n if (signal?.aborted) {\n LedgerAdapter._throwIfAborted(signal);\n }\n const transportType: TransportType = this.activeTransport ?? 'hid';\n\n // Register the wait before emitting — a synchronous listener that replies\n // immediately (e.g. in tests or a same-process consumer) would otherwise\n // resolve before any pending entry exists and the response would drop.\n const waitPromise = this._uiRegistry.wait<DevicePermissionResponse>(\n UI_REQUEST.REQUEST_DEVICE_PERMISSION,\n { timeoutMs: 60_000 }\n );\n\n this.emitter.emit(UI_REQUEST.REQUEST_DEVICE_PERMISSION, {\n type: UI_REQUEST.REQUEST_DEVICE_PERMISSION,\n payload: { transportType, connectId, deviceId },\n });\n\n let response: DevicePermissionResponse;\n const onAbort = () => {\n this._uiRegistry.cancel(UI_REQUEST.REQUEST_DEVICE_PERMISSION);\n };\n try {\n signal?.addEventListener('abort', onAbort, { once: true });\n response = await waitPromise;\n } catch (err) {\n if (signal?.aborted) {\n LedgerAdapter._throwIfAborted(signal);\n }\n // Defensive: same-type re-fire of REQUEST_DEVICE_PERMISSION could\n // preempt this wait. Surface as UserAborted so upstream classifiers\n // stop the batch cleanly instead of bubbling an unmapped tag.\n if ((err as { _tag?: string })?._tag === UI_REQUEST_PREEMPTED_TAG) {\n this.emitter.emit(UI_REQUEST.CLOSE_UI_WINDOW, {\n type: UI_REQUEST.CLOSE_UI_WINDOW,\n payload: {},\n });\n throw Object.assign(new Error('Device permission request superseded'), {\n _tag: ERROR_TAG.UserAborted,\n code: HardwareErrorCode.UserAborted,\n cause: err,\n });\n }\n throw err;\n } finally {\n signal?.removeEventListener('abort', onAbort);\n }\n\n const { granted, reason, message } = response;\n\n if (!granted) {\n throw Object.assign(new Error(message ?? 'Device permission denied'), {\n code: HardwareErrorCode.DevicePermissionDenied,\n reason,\n });\n }\n }\n\n /**\n * Convert a thrown error to a Response failure.\n * Uses mapLedgerError to parse Ledger DMK error codes into HardwareErrorCode values.\n */\n private errorToFailure<T>(err: unknown): Response<T> {\n debugError('[LedgerAdapter] error:', err);\n\n // Preserve `_tag` so SDK classifiers survive the Failure round-trip.\n const tag = err && typeof err === 'object' ? (err as { _tag?: string })._tag : undefined;\n\n // If the error carries an explicit HardwareErrorCode (e.g. validation errors\n // thrown by connector chain methods), use it directly.\n if (\n err &&\n typeof err === 'object' &&\n 'code' in err &&\n typeof (err as { code: unknown }).code === 'number'\n ) {\n const e = err as {\n code: number;\n message?: string;\n appName?: string;\n reason?: string;\n params?: Record<string, unknown>;\n };\n const params =\n e.code === HardwareErrorCode.DevicePermissionDenied && e.reason\n ? { permissionDeniedReason: e.reason }\n : e.params;\n return ledgerFailure(e.code, e.message ?? 'Unknown error', e.appName, tag, params);\n }\n\n const mapped = mapLedgerError(err);\n\n // DeviceLocked is handled by connectorCall retry logic (_waitForDeviceConnect).\n // Do NOT emit UI events here — it would show UI and return error simultaneously.\n\n return ledgerFailure(mapped.code, mapped.message, mapped.appName, tag);\n }\n\n // ---------------------------------------------------------------------------\n // Event translation\n // ---------------------------------------------------------------------------\n\n private deviceConnectHandler = (data: { device: ConnectorDevice }): void => {\n const deviceInfo = this.connectorDeviceToDeviceInfo(data.device);\n this._discoveredDevices.set(deviceInfo.connectId, deviceInfo);\n // Clear any stale session for this connectId so ensureConnected() does a fresh connect.\n // This handles the case where the connector reconnected internally (e.g. TRON app switch).\n this._sessions.delete(deviceInfo.connectId);\n this.emitter.emit(DEVICE.CONNECT, {\n type: DEVICE.CONNECT,\n payload: deviceInfo,\n });\n };\n\n private deviceDisconnectHandler = (data: { connectId: string }): void => {\n this._discoveredDevices.delete(data.connectId);\n this._sessions.delete(data.connectId);\n this.emitter.emit(DEVICE.DISCONNECT, {\n type: DEVICE.DISCONNECT,\n payload: { connectId: data.connectId },\n });\n };\n\n // Forward connector `ui-event` to the public hw.emitter so consumers only\n // need to subscribe in one place. For the AppInstallProgress variant we\n // re-key sessionId → connectId via the live _sessions map; if no mapping\n // exists (race during teardown) we drop. All other variants pass through\n // unchanged.\n private uiEventForwarder = (event: ConnectorUiEvent): void => {\n if (event.type === EConnectorInteraction.AppInstallProgress) {\n let connectId: string | undefined;\n for (const [cid, sid] of this._sessions) {\n if (sid === event.payload.sessionId) {\n connectId = cid;\n break;\n }\n }\n if (!connectId) {\n debugLog(\n '[LedgerAdapter] dropping AppInstallProgress: no connectId for sessionId',\n event.payload.sessionId\n );\n return;\n }\n const { appName, progress } = event.payload;\n const key = `${connectId}:${appName}`;\n // Reset baseline on app/device switch — and after the prior stream\n // finished — so the next install of the same app emits intermediate\n // frames instead of staying stuck at the final 1.0 baseline.\n if (this._installProgressLastKey !== key || this._installProgressLastEmittedValue >= 1) {\n this._installProgressLastEmittedValue = -Infinity;\n this._installProgressLastKey = key;\n }\n const delta = progress - this._installProgressLastEmittedValue;\n if (delta < LedgerAdapter.APP_INSTALL_PROGRESS_MIN_DELTA && progress < 1) {\n return;\n }\n this._installProgressLastEmittedValue = progress;\n this.emitter.emit('ui-event', {\n type: EConnectorInteraction.AppInstallProgress,\n payload: {\n connectId,\n appName,\n progress,\n },\n });\n return;\n }\n this.emitter.emit('ui-event', event);\n };\n\n private registerEventListeners(): void {\n this.connector.on('device-connect', this.deviceConnectHandler);\n this.connector.on('device-disconnect', this.deviceDisconnectHandler);\n this.connector.on('ui-event', this.uiEventForwarder);\n }\n\n private unregisterEventListeners(): void {\n this.connector.off('device-connect', this.deviceConnectHandler);\n this.connector.off('device-disconnect', this.deviceDisconnectHandler);\n this.connector.off('ui-event', this.uiEventForwarder);\n }\n\n // ---------------------------------------------------------------------------\n // Device info mapping\n // ---------------------------------------------------------------------------\n\n private connectorDeviceToDeviceInfo(device: ConnectorDevice): DeviceInfo {\n return {\n vendor: 'ledger',\n model: device.model ?? 'unknown',\n modelName: device.modelName,\n firmwareVersion: '',\n deviceId: device.deviceId,\n connectId: device.connectId,\n label: device.name,\n connectionType: this.connector.connectionType,\n rssi: device.rssi,\n isConnectable: device.isConnectable,\n serialNumber: device.serialNumber,\n capabilities: device.capabilities,\n };\n }\n}\n","import { HardwareErrorCode, enrichErrorMessage } from '@onekeyfe/hwk-adapter-core';\n\nimport type { Failure } from '@onekeyfe/hwk-adapter-core';\n\nexport const MULTIPLE_USB_LEDGER_DEVICES_ERROR_MESSAGE =\n 'Multiple Ledger USB devices are connected. Please connect only one Ledger device and try again.';\n\nexport function createMultipleUsbLedgerDevicesError(): Error & { code: HardwareErrorCode } {\n return Object.assign(new Error(MULTIPLE_USB_LEDGER_DEVICES_ERROR_MESSAGE), {\n code: HardwareErrorCode.DeviceOneDeviceOnly,\n });\n}\n\n// `_tag` survives errorToFailure → re-throw so SDK classifiers keep working.\nexport type LedgerFailure = Omit<Failure, 'payload'> & {\n payload: Failure['payload'] & { appName?: string; _tag?: string };\n};\n\nexport interface WrapErrorOptions {\n /** Fallback when err has no `appName` (DMK signer errors don't carry it). */\n defaultAppName?: string;\n}\n\nexport function ledgerFailure(\n code: HardwareErrorCode,\n error: string,\n appName?: string,\n tag?: string,\n params?: Record<string, unknown>\n): LedgerFailure {\n const payload: LedgerFailure['payload'] = { error, code };\n if (appName !== undefined) payload.appName = appName;\n if (tag !== undefined) payload._tag = tag;\n if (params !== undefined) payload.params = params;\n return { success: false, payload };\n}\n\n/**\n * DMK locked device status codes:\n * 0x5515 (21781) — primary locked response\n * 0x6982 (27010) — security status not satisfied\n * 0x5303 (21251) — tertiary locked response\n */\nconst LOCKED_ERROR_CODES = new Set(['5515', '21781', '6982', '27010', '5303', '21251']);\n\n/**\n * DMK user-rejected status codes:\n * 0x6985 (27013) — conditions of use not satisfied (user denied on device)\n */\nconst USER_REJECTED_CODES = new Set(['6985', '27013']);\n\n/**\n * DMK wrong-app / CLA-not-supported status codes:\n * 0x6e00 (28160) — CLA not supported (wrong app open)\n * 0x6d00 (27904) — INS not supported (wrong app or outdated app)\n * 0x6a83 (27267) — Referenced data not found (wrong app for raw APDU, e.g. TRON)\n */\nconst WRONG_APP_CODES = new Set(['6e00', '28160', '6d00', '27904', '6a83', '27267']);\n\n/**\n * DMK app-not-installed status codes:\n * 0x6807 (26631) — Unknown application name (app not installed on device)\n */\nconst APP_NOT_INSTALLED_CODES = new Set(['6807', '26631']);\n\n/**\n * DMK step value emitted when SignTransactionDeviceAction retries with\n * basic/blind signing. Used to distinguish APDU 0x6a80 (\"Invalid data\")\n * caused by a blind-sign fallback from a generic malformed transaction.\n */\nconst STEP_BLIND_SIGN_TRANSACTION_FALLBACK = 'signer.eth.steps.blindSignTransactionFallback';\nconst STEP_DETECT_BLIND_SIGNING = 'signer.eth.steps.detectBlindSigning';\nconst BLIND_SIGNING_STEPS = new Set([\n STEP_BLIND_SIGN_TRANSACTION_FALLBACK,\n STEP_DETECT_BLIND_SIGNING,\n]);\n\nfunction normalizeApduHex(value: unknown): string | null {\n if (typeof value === 'number' && Number.isInteger(value) && value >= 0 && value <= 0xffff) {\n return value.toString(16).padStart(4, '0');\n }\n if (typeof value !== 'string') return null;\n const raw = value.toLowerCase().replace(/^0x/, '');\n return /^[0-9a-f]{1,4}$/i.test(raw) ? raw.padStart(4, '0') : null;\n}\n\n/**\n * Read the Ledger Ethereum App APDU error code from a DMK error object.\n * Returns the code in lowercase (e.g. \"6a80\") or `null` if not present.\n */\nfunction getEthAppErrorCode(err: unknown): string | null {\n if (!err || typeof err !== 'object') return null;\n const e = err as Record<string, unknown>;\n if (e._tag === ERROR_TAG.EthAppCommand) {\n const code =\n normalizeApduHex(e.errorCode) ?? normalizeApduHex(e.statusCode) ?? normalizeApduHex(e.code);\n if (code) return code;\n }\n const orig = e.originalError as Record<string, unknown> | undefined;\n if (orig?._tag === ERROR_TAG.EthAppCommand) {\n return (\n normalizeApduHex(orig.errorCode) ??\n normalizeApduHex(orig.statusCode) ??\n normalizeApduHex(orig.code)\n );\n }\n return null;\n}\n\n/**\n * Extract an APDU status word in lowercase hex. Handles DMK's hex-string\n * `errorCode`, numeric `statusCode`, and recurses through\n * `originalError` for wrapped errors.\n */\nfunction extractApduHex(err: unknown): string | null {\n if (!err || typeof err !== 'object') return null;\n const e = err as Record<string, unknown>;\n const direct = normalizeApduHex(e.errorCode) ?? normalizeApduHex(e.statusCode);\n if (direct) return direct;\n if (e.originalError != null) {\n const nested = extractApduHex(e.originalError);\n if (nested) return nested;\n }\n if (e.error != null && typeof e._tag === 'string') {\n const nested = extractApduHex(e.error);\n if (nested) return nested;\n }\n return null;\n}\n\n/** Solana APDU → code. 0x6808 arrives as a plain DeviceExchangeError,\n * not wrapped in SolanaAppCommandError, so match by code only. */\nfunction mapSolanaAppError(hex: string): HardwareErrorCode | null {\n switch (hex) {\n case '6808':\n return HardwareErrorCode.SolanaBlindSigningRequired;\n default:\n return null;\n }\n}\n\n/** Tron APDU → code. Source: app-tron/src/app_errors.h (E_MISSING_SETTING_*). */\nfunction mapTronAppError(hex: string): HardwareErrorCode | null {\n switch (hex) {\n case '6a8d':\n return HardwareErrorCode.TronCustomContractRequired;\n case '6a8b':\n return HardwareErrorCode.TronDataSigningRequired;\n case '6a8c':\n return HardwareErrorCode.TronSignByHashRequired;\n default:\n return null;\n }\n}\n\n/** BTC APDU → code. 0xb000 range is disjoint from other apps' 0x6xxx. */\nfunction mapBtcAppError(hex: string): HardwareErrorCode | null {\n switch (hex) {\n case 'b008':\n return HardwareErrorCode.BtcWalletPolicyHmacMismatch;\n case 'b007':\n return HardwareErrorCode.BtcUnexpectedState;\n default:\n return null;\n }\n}\n\n/**\n * Map unambiguous Ledger Ethereum App APDU status words to HardwareErrorCode.\n * Ambiguous status words, such as 0x6a80, are classified with full error\n * context in `classifyEthAppError`.\n */\nfunction mapEthAppErrorCode(ethCode: string): HardwareErrorCode | null {\n switch (ethCode) {\n case '6984':\n return HardwareErrorCode.EvmClearSignPluginMissing;\n case '6a84':\n return HardwareErrorCode.EvmDataTooLarge;\n case '6501':\n return HardwareErrorCode.EvmTxTypeNotSupported;\n case '911c':\n return HardwareErrorCode.AppTooOld;\n default:\n return null;\n }\n}\n\nfunction classifyEthAppError(err: unknown): HardwareErrorCode | null {\n const ethCode = getEthAppErrorCode(err);\n if (!ethCode) return null;\n\n // 0x6a80 is a broad \"Invalid data\" APDU. Only report blind-signing\n // guidance when DMK actually entered the blind-signing flow.\n if (ethCode === '6a80') {\n return hasBlindSigningStep(err) ? HardwareErrorCode.EvmBlindSigningRequired : null;\n }\n\n return mapEthAppErrorCode(ethCode);\n}\n\nfunction classifyBlindSigningDetectionError(err: unknown): HardwareErrorCode | null {\n if (!hasBlindSigningStep(err)) return null;\n if (hasInvalidArgumentCode(err)) return HardwareErrorCode.EvmBlindSigningRequired;\n return null;\n}\n\n// Centralized `_tag` constants — single source of truth for both writes and\n// classifier comparisons. Typos fail at compile time.\nexport const ERROR_TAG = {\n // SDK-mint\n DeviceNotAdvertising: 'DeviceNotAdvertisingError', // BLE scan miss\n DeviceNotInDiscoveryCache: 'DeviceNotInDiscoveryCacheError', // dm.connect() before enumerate\n BlePairingTimeout: 'BlePairingTimeoutError', // SMP 30s timeout\n BleGattBondingFailed: 'BleGattBondingFailedError', // other GATT failure\n UserAborted: 'UserAborted',\n DeviceAppStuck: 'DeviceAppStuck', // chain app wedged (APDU 0x6901)\n DeviceTransportStuck: 'DeviceTransportStuck', // DMK transport queue wedged\n // installApp resolved success but the app is still missing on device —\n // DMK quirk. Surfaced as a distinct tag so callers can tell it apart from\n // the original DMK-thrown AppNotInstalled.\n AppInstallVerifyFailed: 'AppInstallVerifyFailedError',\n\n // DMK-reuse (DMK throws same string; we synthesize too)\n DeviceLocked: 'DeviceLockedError',\n DeviceNotRecognized: 'DeviceNotRecognizedError',\n DeviceSessionNotFound: 'DeviceSessionNotFound',\n OpenAppCommand: 'OpenAppCommandError',\n\n // DMK-only (read only)\n EthAppCommand: 'EthAppCommandError',\n UserRefusedOnDevice: 'UserRefusedOnDevice',\n WrongAppOpened: 'WrongAppOpenedError',\n InvalidStatusWord: 'InvalidStatusWordError',\n AlreadySendingApdu: 'AlreadySendingApduError',\n UnknownDeviceExchange: 'UnknownDeviceExchangeError',\n NoAccessibleDevice: 'NoAccessibleDeviceError',\n UnknownDevice: 'UnknownDeviceError',\n DeviceSessionRefresher: 'DeviceSessionRefresherError',\n DeviceNotInitialized: 'DeviceNotInitializedError',\n OpeningConnection: 'OpeningConnectionError',\n DeviceDisconnectedBeforeSendingApdu: 'DeviceDisconnectedBeforeSendingApdu',\n DeviceDisconnectedWhileSending: 'DeviceDisconnectedWhileSendingError',\n Disconnect: 'DisconnectError',\n ReconnectionFailed: 'ReconnectionFailedError',\n WebHIDDisconnect: 'WebHIDDisconnectError',\n // ble-plx surfaces this when GATT notification setup fails — typical\n // outcome when the user doesn't confirm pairing on the device, or the\n // existing bond is invalid. Observed in production after ~30s.\n PairingRefused: 'PairingRefusedError',\n // DMK remote-network failures (manager-api HTTP / secure-channel WS).\n WebSocketConnection: 'WebSocketConnectionError',\n HttpFetch: 'FetchError',\n InvalidFirmwareMetadataResponse: 'InvalidGetFirmwareMetadataResponseError',\n} as const;\n\nexport type SdkErrorTag = (typeof ERROR_TAG)[keyof typeof ERROR_TAG];\n\n// Strict: only SE-locked. DeviceNotAdvertising / BlePairingTimeout etc are\n// their own classifiers — don't conflate.\nexport function isDeviceLockedError(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false;\n const e = err as Record<string, unknown>;\n if (e.errorCode != null && LOCKED_ERROR_CODES.has(String(e.errorCode))) return true;\n if (e.statusCode != null && LOCKED_ERROR_CODES.has(String(e.statusCode))) return true;\n if (e._tag === ERROR_TAG.DeviceLocked) return true;\n if (e.originalError != null && isDeviceLockedError(e.originalError)) return true;\n if (e.error != null && e._tag && isDeviceLockedError(e.error)) return true;\n return false;\n}\n\n// BLE scan miss — peripheral not seen, recoverable via unlock prompt.\nexport function isDeviceNotAdvertisingError(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false;\n return (err as { _tag?: string })._tag === ERROR_TAG.DeviceNotAdvertising;\n}\n\n// GATT bonding failed (non-timeout). Not auto-retryable.\nexport function isBleGattBondingFailedError(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false;\n return (err as { _tag?: string })._tag === ERROR_TAG.BleGattBondingFailed;\n}\n\n// Any BLE pairing failure (DMK-native, ble-plx, our own). All map to\n// `code: BlePairingTimeout` so batch fail-closes uniformly. User-cancel of\n// the system pairing dialog also lands here — to the user it's the same\n// \"didn't pair\" outcome, no need to disambiguate.\nconst PAIRING_FAILURE_TAGS = new Set<string>([\n ERROR_TAG.BlePairingTimeout,\n ERROR_TAG.BleGattBondingFailed,\n ERROR_TAG.PairingRefused,\n]);\nexport function isBlePairingFailureError(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false;\n const tag = (err as { _tag?: string })._tag;\n if (tag && PAIRING_FAILURE_TAGS.has(tag)) return true;\n const orig = (err as { originalError?: unknown }).originalError;\n if (orig != null && isBlePairingFailureError(orig)) return true;\n return false;\n}\n\n// \"Connection is broken\" — next call can't reuse the session. Used by\n// Layer 2 fail-closed gate.\nconst CONNECTION_LEVEL_TAGS: Set<string> = new Set([\n ERROR_TAG.DeviceLocked,\n ERROR_TAG.DeviceNotAdvertising,\n ERROR_TAG.BlePairingTimeout,\n ERROR_TAG.BleGattBondingFailed,\n ERROR_TAG.PairingRefused,\n ERROR_TAG.DeviceNotRecognized,\n ERROR_TAG.NoAccessibleDevice,\n ERROR_TAG.UnknownDevice,\n ERROR_TAG.DeviceSessionNotFound,\n ERROR_TAG.DeviceSessionRefresher,\n ERROR_TAG.DeviceNotInitialized,\n ERROR_TAG.OpeningConnection,\n ERROR_TAG.DeviceDisconnectedBeforeSendingApdu,\n ERROR_TAG.DeviceDisconnectedWhileSending,\n ERROR_TAG.Disconnect,\n ERROR_TAG.ReconnectionFailed,\n ERROR_TAG.WebHIDDisconnect,\n]);\n\nconst DEVICE_NOT_FOUND_TAGS: Set<string> = new Set([\n ERROR_TAG.NoAccessibleDevice,\n ERROR_TAG.UnknownDevice,\n ERROR_TAG.DeviceNotInitialized,\n // SDK-internal: dm.connect() called before _discovered was populated.\n // Map to DeviceNotFound so non-BLE-direct paths get a sensible error code.\n ERROR_TAG.DeviceNotInDiscoveryCache,\n]);\n\nconst DEVICE_BUSY_TAGS: Set<string> = new Set([ERROR_TAG.OpeningConnection]);\n\nconst DEVICE_DISCONNECTED_TAGS: Set<string> = new Set([\n ERROR_TAG.DeviceNotRecognized,\n ERROR_TAG.DeviceSessionNotFound,\n ERROR_TAG.DeviceSessionRefresher,\n ERROR_TAG.DeviceDisconnectedBeforeSendingApdu,\n ERROR_TAG.DeviceDisconnectedWhileSending,\n ERROR_TAG.Disconnect,\n ERROR_TAG.ReconnectionFailed,\n ERROR_TAG.WebHIDDisconnect,\n]);\n\nexport function isConnectionLevelError(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false;\n const tag = (err as { _tag?: string })._tag;\n if (tag && CONNECTION_LEVEL_TAGS.has(tag)) return true;\n // Recurse into nested DMK error envelopes (originalError / error.{_tag})\n const e = err as Record<string, unknown>;\n if (e.originalError != null && isConnectionLevelError(e.originalError)) return true;\n if (e.error != null && e._tag && isConnectionLevelError(e.error)) return true;\n return false;\n}\n\n/** Expose for connector — used to decide whether to pass an error through\n * unchanged or wrap as BleGattBondingFailed. */\nexport function isKnownConnectionTag(tag: unknown): boolean {\n return typeof tag === 'string' && CONNECTION_LEVEL_TAGS.has(tag);\n}\n\n/** Check if a status/error code exists in the given set, crawling the error chain. */\nfunction hasStatusCode(err: unknown, codeSet: Set<string>): boolean {\n if (!err || typeof err !== 'object') return false;\n const e = err as Record<string, unknown>;\n if (e.errorCode != null && codeSet.has(String(e.errorCode))) return true;\n if (e.statusCode != null && codeSet.has(String(e.statusCode))) return true;\n if (e.originalError != null && hasStatusCode(e.originalError, codeSet)) return true;\n if (e.error != null && e._tag && hasStatusCode(e.error, codeSet)) return true;\n return false;\n}\n\nfunction hasDeviceActionStep(err: unknown, step: string): boolean {\n if (!err || typeof err !== 'object') return false;\n const e = err as Record<string, unknown>;\n\n if (e._lastStep === step) return true;\n\n if (Array.isArray(e._deviceActionSteps) && e._deviceActionSteps.includes(step)) {\n return true;\n }\n\n if (e.originalError != null && hasDeviceActionStep(e.originalError, step)) return true;\n if (e.error != null && e._tag && hasDeviceActionStep(e.error, step)) return true;\n return false;\n}\n\nfunction hasBlindSigningStep(err: unknown): boolean {\n for (const step of BLIND_SIGNING_STEPS) {\n if (hasDeviceActionStep(err, step)) return true;\n }\n return false;\n}\n\nfunction hasInvalidArgumentCode(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false;\n const e = err as Record<string, unknown>;\n if (e.code === 'INVALID_ARGUMENT') return true;\n if (typeof e.message === 'string' && e.message.includes('code=INVALID_ARGUMENT')) return true;\n if (e.originalError != null && hasInvalidArgumentCode(e.originalError)) return true;\n if (e.error != null && e._tag && hasInvalidArgumentCode(e.error)) return true;\n return false;\n}\n\nfunction isDeviceNotFoundError(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false;\n const tag = (err as { _tag?: string })._tag;\n if (tag && DEVICE_NOT_FOUND_TAGS.has(tag)) return true;\n const e = err as Record<string, unknown>;\n if (e.originalError != null && isDeviceNotFoundError(e.originalError)) return true;\n if (e.error != null && e._tag && isDeviceNotFoundError(e.error)) return true;\n return false;\n}\n\nfunction isDeviceBusyError(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false;\n const tag = (err as { _tag?: string })._tag;\n if (tag && DEVICE_BUSY_TAGS.has(tag)) return true;\n const e = err as Record<string, unknown>;\n if (e.originalError != null && isDeviceBusyError(e.originalError)) return true;\n if (e.error != null && e._tag && isDeviceBusyError(e.error)) return true;\n return false;\n}\n\n/** Check for user rejection (denied on device). */\nexport function isUserRejectedError(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false;\n const e = err as Record<string, unknown>;\n if (e._tag === ERROR_TAG.UserRefusedOnDevice) return true;\n if (typeof e.message === 'string' && /denied|rejected|refused/i.test(e.message)) return true;\n if (hasStatusCode(err, USER_REJECTED_CODES)) return true;\n return false;\n}\n\n/** Check for SDK-level user abort (declined install prompt, cancelled UI flow). */\nexport function isUserAbortedError(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false;\n const e = err as Record<string, unknown>;\n return e._tag === ERROR_TAG.UserAborted;\n}\n\n/** Check for wrong app open on the device. */\nexport function isWrongAppError(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false;\n const e = err as Record<string, unknown>;\n if (e._tag === ERROR_TAG.WrongAppOpened || e._tag === ERROR_TAG.InvalidStatusWord) {\n if (hasStatusCode(err, WRONG_APP_CODES)) return true;\n }\n if (typeof e.message === 'string') {\n const msg = e.message.toLowerCase();\n if (msg.includes('wrong app') || msg.includes('open the') || msg.includes('cla not supported'))\n return true;\n }\n if (hasStatusCode(err, WRONG_APP_CODES)) return true;\n return false;\n}\n\n/** Check for app not installed on device. */\nexport function isAppNotInstalledError(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false;\n const e = err as Record<string, unknown>;\n if (typeof e.message === 'string' && /unknown application/i.test(e.message)) return true;\n if (hasStatusCode(err, APP_NOT_INSTALLED_CODES)) return true;\n return false;\n}\n\n/** DMK install ran out of space on the device. Identified by the DMK error tag. */\nexport function isOutOfMemoryError(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false;\n const e = err as Record<string, unknown>;\n return e._tag === 'OutOfMemoryDAError';\n}\n\n/** Remote network failure reaching Ledger's servers (HTTP or WS). Crawls the error chain. */\nconst NETWORK_ERROR_TAGS = new Set<string>([\n ERROR_TAG.WebSocketConnection,\n ERROR_TAG.HttpFetch,\n ERROR_TAG.InvalidFirmwareMetadataResponse,\n]);\nexport function isNetworkError(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false;\n const e = err as Record<string, unknown>;\n const tag = e._tag;\n if (typeof tag === 'string' && NETWORK_ERROR_TAGS.has(tag)) return true;\n if (e.originalError != null && isNetworkError(e.originalError)) return true;\n if (e.error != null && isNetworkError(e.error)) return true;\n return false;\n}\n\n/** Check for device disconnected errors. */\nexport function isDeviceDisconnectedError(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false;\n const e = err as Record<string, unknown>;\n const tag = e._tag;\n if (typeof tag === 'string' && DEVICE_DISCONNECTED_TAGS.has(tag)) return true;\n if (typeof e.message === 'string') {\n const msg = e.message.toLowerCase();\n if (\n msg.includes('disconnected') ||\n msg.includes('not found') ||\n msg.includes('no device') ||\n msg.includes('unplugged')\n )\n return true;\n }\n return false;\n}\n\n/**\n * DMK timeout error _tag values.\n * These are the concrete error classes from @ledgerhq/device-management-kit.\n */\nconst TIMEOUT_TAGS = new Set([\n 'DeviceExchangeTimeoutError',\n 'SendApduTimeoutError',\n 'SendCommandTimeoutError',\n]);\n\n/** Check for timeout errors using DMK's _tag identifiers or wrapped error code. */\nexport function isTimeoutError(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false;\n const e = err as Record<string, unknown>;\n if (typeof e._tag === 'string' && TIMEOUT_TAGS.has(e._tag)) return true;\n if (e.code === HardwareErrorCode.OperationTimeout) return true;\n return false;\n}\n\n/** Chain app wedged: APDU 0x6901 — only the user pressing both buttons recovers. */\nexport function isAppStuckByApdu(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false;\n const tag = (err as Record<string, unknown>)._tag;\n if (tag === ERROR_TAG.DeviceAppStuck) return true; // already wrapped form\n return extractApduHex(err) === '6901';\n}\n\n/** DMK transport / IntentQueue slot wedged — recover via connector.reset(). */\nexport function isTransportStuck(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false;\n const tag = (err as Record<string, unknown>)._tag;\n return (\n tag === ERROR_TAG.DeviceTransportStuck || // already wrapped form\n tag === ERROR_TAG.UnknownDeviceExchange ||\n tag === ERROR_TAG.AlreadySendingApdu\n );\n}\n\n/** Union: any stuck state, regardless of root cause. Used by Layer 2 catch. */\nexport function isStuckAppStateError(err: unknown): boolean {\n return isAppStuckByApdu(err) || isTransportStuck(err);\n}\n\n/**\n * Map a Ledger DMK error to a HardwareErrorCode and human-readable message.\n * `opts.defaultAppName` fills `appName` when the raw error doesn't carry it\n * (DMK signer errors don't).\n */\nexport function mapLedgerError(\n err: unknown,\n opts?: WrapErrorOptions\n): {\n code: HardwareErrorCode;\n message: string;\n appName?: string;\n} {\n // Order matters: check more specific errors first\n\n // Extract the original message for fallback / enrichment\n let originalMessage = 'Unknown Ledger error';\n if (err instanceof Error) {\n originalMessage = err.message;\n } else if (err && typeof err === 'object') {\n const e = err as Record<string, unknown>;\n originalMessage = String(e.message ?? e._tag ?? e.type ?? JSON.stringify(err));\n }\n\n let code: HardwareErrorCode;\n\n // DeviceLocked: _tag handoff (unlock-device) or APDU 0x5515/0x6982.\n if (isDeviceLockedError(err)) {\n code = HardwareErrorCode.DeviceLocked;\n } else if (isDeviceNotAdvertisingError(err) || isDeviceNotFoundError(err)) {\n code = HardwareErrorCode.DeviceNotFound;\n } else if (isDeviceBusyError(err)) {\n code = HardwareErrorCode.DeviceBusy;\n } else if (isBlePairingFailureError(err)) {\n code = HardwareErrorCode.BlePairingTimeout;\n } else if (isUserAbortedError(err)) {\n // SDK-level abort (e.g. user declined the install prompt). Distinct from\n // on-device UserRejected — surface UserAborted so callers can tell apart\n // \"I closed the dialog\" from \"I pressed reject on the device\".\n code = HardwareErrorCode.UserAborted;\n } else if (isUserRejectedError(err)) {\n // User rejection (0x6985) must win over EthAppError mapping — a user-cancelled\n // blind-sign is not a \"please enable Blind signing\" situation.\n code = HardwareErrorCode.UserRejected;\n } else if (isWrongAppError(err)) {\n code = HardwareErrorCode.WrongApp;\n } else if (isAppNotInstalledError(err)) {\n code = HardwareErrorCode.AppNotInstalled;\n } else if (isOutOfMemoryError(err)) {\n code = HardwareErrorCode.DeviceOutOfMemory;\n } else if (isNetworkError(err)) {\n // Must precede isDeviceDisconnectedError — its message-substring match can trip on network errors.\n code = HardwareErrorCode.NetworkError;\n } else if (isDeviceDisconnectedError(err)) {\n code = HardwareErrorCode.DeviceDisconnected;\n } else if (isTimeoutError(err)) {\n code = HardwareErrorCode.OperationTimeout;\n } else {\n const ethMapped = classifyEthAppError(err) ?? classifyBlindSigningDetectionError(err);\n\n // Solana / Tron / BTC APDU codes — disjoint from EVM's table, single-pass lookup.\n const apduHex = ethMapped ? null : extractApduHex(err);\n const chainMapped = apduHex\n ? mapSolanaAppError(apduHex) ?? mapTronAppError(apduHex) ?? mapBtcAppError(apduHex)\n : null;\n\n code = ethMapped ?? chainMapped ?? HardwareErrorCode.UnknownError;\n }\n\n const errAppName =\n err && typeof err === 'object'\n ? ((err as Record<string, unknown>).appName as string | undefined)\n : undefined;\n const appName = errAppName ?? opts?.defaultAppName;\n\n return { code, message: enrichErrorMessage(code, originalMessage), appName };\n}\n","import { HardwareErrorCode, failure, success } from '@onekeyfe/hwk-adapter-core';\n\nimport { debugLog } from '../../utils/debugLog';\n\nimport type {\n AllNetworkAddressParams,\n AllNetworkAddressResponse,\n AllNetworkGetAddressParams,\n BtcAddress,\n BtcPublicKey,\n ChainForFingerprint,\n EvmAddress,\n ICommonCallParams,\n Response,\n SolAddress,\n TronAddress,\n} from '@onekeyfe/hwk-adapter-core';\n\nexport type LedgerInstallAppContext = {\n deviceOutOfMemoryError?: Error;\n /**\n * Apps for which installApp has resolved (successfully or not) within\n * this bundle. Prevents an install-loop when DMK reports installApp\n * success but the app is still missing on the device — without this,\n * the retried main call would hit AppNotInstalled again and re-enter\n * the install flow, prompting the user a second time.\n */\n installAttemptedAppNames?: Set<string>;\n};\n\nexport type LedgerCallChain = <T>(\n connectId: string,\n deviceId: string,\n chain: string,\n method: string,\n params: unknown,\n commonParams?: ICommonCallParams,\n skipFingerprint?: boolean,\n installContext?: LedgerInstallAppContext\n) => Promise<Response<T>>;\n\nexport type LedgerGetChainFingerprint = (\n connectId: string,\n chain: ChainForFingerprint\n) => Promise<Response<string>>;\n\ntype LedgerAllNetworkMethod =\n | 'evmGetAddress'\n | 'btcGetAddress'\n | 'btcGetPublicKey'\n | 'solGetAddress'\n | 'tronGetAddress';\n\nconst LEDGER_BTC_NETWORK_COIN_MAP: Partial<Record<string, string>> = {\n tbtc: 'Testnet',\n bch: 'Bcash',\n doge: 'Dogecoin',\n ltc: 'Litecoin',\n neurai: 'Neurai',\n};\n\nexport function createAllNetworkGetAddress({\n callChain,\n getChainFingerprint,\n}: {\n callChain: LedgerCallChain;\n getChainFingerprint: LedgerGetChainFingerprint;\n}) {\n return async function allNetworkGetAddress(\n connectId: string,\n _deviceId: string,\n params: AllNetworkGetAddressParams\n ): Promise<Response<AllNetworkAddressResponse[]>> {\n // Bundle-level REQ/RES. Each item inside still produces its own [REQ]/[RES]\n // pair via connectorCall — this top-level trace shows the batch shape so a\n // log reader can correlate the user's intent with the per-item activity.\n debugLog('[LedgerAdapter][REQ]', { method: 'allNetworkGetAddress', connectId, params });\n\n const installContext: LedgerInstallAppContext = {};\n const commonParams: ICommonCallParams = {\n autoInstallApp: params.autoInstallApp,\n };\n const responses: AllNetworkAddressResponse[] = [];\n const chainFingerprints = new Map<ChainForFingerprint, string>();\n\n for (const item of params.bundle) {\n const method = getAllNetworkMethod(item);\n if (!method) {\n responses.push(buildUnsupportedMethodResponse(item));\n } else {\n const chain = getFingerprintChain(method);\n const itemDeviceId = getItemDeviceId(item) ?? chainFingerprints.get(chain) ?? '';\n const normalizedItem = normalizeLedgerAllNetworkItem(method, item);\n const response = await callAllNetworkItem(\n callChain,\n getChainFingerprint,\n connectId,\n itemDeviceId,\n chain,\n method,\n normalizedItem,\n commonParams,\n installContext,\n chainFingerprints\n );\n if (isTopLevelAllNetworkFailure(response)) {\n const code = response.payload?.code ?? HardwareErrorCode.DeviceMismatch;\n const result = failure(\n code,\n response.payload?.error ?? 'All-network get-address aborted',\n response.payload?.params\n );\n debugLog('[LedgerAdapter][RES]', {\n method: 'allNetworkGetAddress',\n success: false,\n payload: result,\n });\n return result;\n }\n responses.push(response);\n }\n }\n\n const result = success(responses);\n debugLog('[LedgerAdapter][RES]', {\n method: 'allNetworkGetAddress',\n success: true,\n payload: result,\n });\n return result;\n };\n}\n\nfunction isTopLevelAllNetworkFailure(response: AllNetworkAddressResponse): boolean {\n if (response.success) {\n return false;\n }\n const code = response.payload?.code;\n // User said \"no\" — SDK-dialog cancel and on-device reject both end the batch.\n return (\n code === HardwareErrorCode.DeviceMismatch ||\n code === HardwareErrorCode.UserAborted ||\n code === HardwareErrorCode.UserRejected\n );\n}\n\nfunction getItemDeviceId(item: AllNetworkAddressParams): string | undefined {\n const { deviceId } = item as { deviceId?: unknown };\n return typeof deviceId === 'string' && deviceId.length > 0 ? deviceId : undefined;\n}\n\nfunction getAllNetworkMethod(item: AllNetworkAddressParams): LedgerAllNetworkMethod | undefined {\n switch (item.methodName) {\n case 'evmGetAddress':\n case 'btcGetAddress':\n case 'btcGetPublicKey':\n case 'solGetAddress':\n case 'tronGetAddress':\n return item.methodName;\n default:\n return undefined;\n }\n}\n\nfunction buildUnsupportedMethodResponse(item: AllNetworkAddressParams): AllNetworkAddressResponse {\n return {\n ...item,\n success: false,\n payload: {\n code: HardwareErrorCode.InvalidParams,\n error: `Unsupported allNetwork method: ${String(item.methodName)}`,\n },\n };\n}\n\nfunction normalizeLedgerAllNetworkItem(\n method: LedgerAllNetworkMethod,\n item: AllNetworkAddressParams\n): AllNetworkAddressParams {\n if (method !== 'btcGetAddress' && method !== 'btcGetPublicKey') {\n return item;\n }\n\n const itemWithCoin = item as AllNetworkAddressParams & { coin?: unknown };\n if (itemWithCoin.coin) {\n return item;\n }\n\n const coin = LEDGER_BTC_NETWORK_COIN_MAP[item.network];\n return coin ? { ...item, coin } : item;\n}\n\nasync function callAllNetworkItem(\n callChain: LedgerCallChain,\n getChainFingerprint: LedgerGetChainFingerprint,\n connectId: string,\n deviceId: string,\n chain: ChainForFingerprint,\n method: LedgerAllNetworkMethod,\n item: AllNetworkAddressParams,\n commonParams: ICommonCallParams,\n installContext: LedgerInstallAppContext,\n chainFingerprints: Map<ChainForFingerprint, string>\n): Promise<AllNetworkAddressResponse> {\n const response = await callAllNetworkMethod(\n callChain,\n connectId,\n deviceId,\n method,\n item,\n commonParams,\n installContext\n );\n\n if (!response.success) {\n return { ...item, success: false, payload: response.payload };\n }\n\n const payload = response.payload as Record<string, unknown>;\n const fingerprint =\n deviceId ||\n chainFingerprints.get(chain) ||\n (await bootstrapChainFingerprint(getChainFingerprint, connectId, chain));\n\n if (!fingerprint) {\n return buildFingerprintBootstrapFailure(item, chain);\n }\n chainFingerprints.set(chain, fingerprint);\n\n return {\n ...item,\n success: true,\n payload: {\n ...payload,\n chainFingerprint: fingerprint,\n chainFingerprintChain: chain,\n },\n };\n}\n\nasync function bootstrapChainFingerprint(\n getChainFingerprint: LedgerGetChainFingerprint,\n connectId: string,\n chain: ChainForFingerprint\n): Promise<string> {\n const response = await getChainFingerprint(connectId, chain);\n return response.success ? response.payload : '';\n}\n\nfunction buildFingerprintBootstrapFailure(\n item: AllNetworkAddressParams,\n chain: ChainForFingerprint\n): AllNetworkAddressResponse {\n return {\n ...item,\n success: false,\n payload: {\n code: HardwareErrorCode.DeviceMismatch,\n error: `Could not establish chain fingerprint for ${chain} after device call; refusing to return unverifiable result. Please retry.`,\n },\n };\n}\n\nfunction getFingerprintChain(method: LedgerAllNetworkMethod): ChainForFingerprint {\n switch (method) {\n case 'evmGetAddress':\n return 'evm';\n case 'btcGetAddress':\n case 'btcGetPublicKey':\n return 'btc';\n case 'solGetAddress':\n return 'sol';\n case 'tronGetAddress':\n return 'tron';\n default:\n throw Object.assign(new Error(`Unsupported allNetwork method: ${method}`), {\n code: HardwareErrorCode.InvalidParams,\n });\n }\n}\n\nasync function callAllNetworkMethod(\n callChain: LedgerCallChain,\n connectId: string,\n deviceId: string,\n method: LedgerAllNetworkMethod,\n item: AllNetworkAddressParams,\n commonParams: ICommonCallParams,\n installContext: LedgerInstallAppContext\n): Promise<Response<unknown>> {\n switch (method) {\n case 'evmGetAddress':\n return callChain<EvmAddress>(\n connectId,\n deviceId,\n 'evm',\n 'evmGetAddress',\n item,\n commonParams,\n false,\n installContext\n );\n case 'btcGetAddress':\n return callChain<BtcAddress>(\n connectId,\n deviceId,\n 'btc',\n 'btcGetAddress',\n item,\n commonParams,\n false,\n installContext\n );\n case 'btcGetPublicKey':\n return callChain<BtcPublicKey>(\n connectId,\n deviceId,\n 'btc',\n 'btcGetPublicKey',\n item,\n commonParams,\n false,\n installContext\n );\n case 'solGetAddress':\n return callChain<SolAddress>(\n connectId,\n deviceId,\n 'sol',\n 'solGetAddress',\n item,\n commonParams,\n false,\n installContext\n );\n case 'tronGetAddress':\n return callChain<TronAddress>(\n connectId,\n deviceId,\n 'tron',\n 'tronGetAddress',\n item,\n commonParams,\n false,\n installContext\n );\n default:\n throw Object.assign(new Error(`Unsupported allNetwork method: ${method}`), {\n code: HardwareErrorCode.InvalidParams,\n });\n }\n}\n","/**\n * SDK-global event bus. Per-runtime singleton — each process subscribes\n * independently; cross-process hosts forward events over their own IPC.\n */\n\nexport type SdkLogEvent = {\n type: 'log';\n level: 'debug' | 'error';\n /** Pre-stringified payload. */\n message: string;\n};\n\n/** Add new variants here; hosts dispatch on `event.type`. */\nexport type SdkEvent = SdkLogEvent;\n\nexport type SdkEventListener = (event: SdkEvent) => void;\n\nconst listeners = new Set<SdkEventListener>();\n\nexport function onSdkEvent(listener: SdkEventListener): () => void {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n}\n\nexport function offSdkEvent(listener: SdkEventListener): void {\n listeners.delete(listener);\n}\n\nexport function emitSdkEvent(event: SdkEvent): void {\n if (listeners.size === 0) return;\n for (const listener of listeners) {\n try {\n listener(event);\n } catch {\n // Misbehaving listeners must not take down the SDK.\n }\n }\n}\n\n/** Stringify args once and emit a log event. No-op when no subscribers. */\nexport function emitLog(level: 'debug' | 'error', ...args: unknown[]): void {\n if (listeners.size === 0) return;\n const message = args.map(a => (typeof a === 'string' ? a : safeStringify(a))).join(' ');\n emitSdkEvent({ type: 'log', level, message });\n}\n\nfunction safeStringify(value: unknown): string {\n if (value instanceof Error) {\n return value.stack ? `${value.message}\\n${value.stack}` : value.message;\n }\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n","/** SDK-internal log helpers. Emit through `sdkEventBus`; silent if nobody subscribes. */\nimport { emitLog } from './sdkEventBus';\n\nexport function debugLog(...args: unknown[]): void {\n emitLog('debug', ...args);\n}\n\nexport function debugError(...args: unknown[]): void {\n emitLog('error', ...args);\n}\n","import type { ConnectionType, DeviceDescriptor } from '@onekeyfe/hwk-adapter-core';\n\n/**\n * Ledger DMK transport identifiers that represent BLE devices.\n *\n * Known today:\n * - \"BLE\": generic/web BLE descriptors\n * - \"RN_BLE\": @ledgerhq/device-transport-kit-react-native-ble\n *\n * Keep the suffix check here so future DMK BLE transports (for example\n * \"FOO_BLE\") are handled in one place instead of scattering string checks.\n */\nexport function isLedgerDmkBleTransport(transport?: string): boolean {\n const normalized = transport?.toUpperCase();\n return normalized === 'BLE' || normalized?.endsWith('_BLE') === true;\n}\n\nexport function isLedgerBleConnectionType(connectionType?: ConnectionType): boolean {\n return connectionType === 'ble';\n}\n\nexport function isLedgerBleDescriptor(\n connectionType: ConnectionType,\n descriptor: DeviceDescriptor\n): boolean {\n return isLedgerBleConnectionType(connectionType) || isLedgerDmkBleTransport(descriptor.transport);\n}\n","import {\n EConnectorInteraction,\n HardwareErrorCode,\n serializeConnectorError,\n} from '@onekeyfe/hwk-adapter-core';\n\nimport { LedgerDeviceManager } from '../device/LedgerDeviceManager';\nimport { SignerManager } from '../signer/SignerManager';\nimport {\n ERROR_TAG,\n isAppStuckByApdu,\n isKnownConnectionTag,\n isTransportStuck,\n mapLedgerError,\n} from '../errors';\nimport { debugLog } from '../utils/debugLog';\nimport { isLedgerBleConnectionType } from '../utils/ledgerDmkTransport';\nimport {\n btcGetAddress,\n btcGetMasterFingerprint,\n btcGetPublicKey,\n btcSignMessage,\n btcSignPsbt,\n btcSignTransaction,\n evmGetAddress,\n evmSignMessage,\n evmSignTransaction,\n evmSignTypedData,\n solGetAddress,\n solSignMessage,\n solSignTransaction,\n tronGetAddress,\n tronSignMessage,\n tronSignTransaction,\n} from './chains';\nimport { DeviceAppsManager } from '../device-apps/DeviceAppsManager';\nimport { collapseSignerInteraction } from './chains/utils';\n\nimport type {\n DeviceApps,\n InstallAppCallParams,\n ListInstalledAppsCallParams,\n} from '../device-apps/DeviceApps';\nimport type { ConnectorContext } from './chains/types';\nimport type { WrapErrorOptions } from '../errors';\nimport type { CancelReason } from '../signer/deviceActionToPromise';\nimport type { DeviceManagementKit } from '@ledgerhq/device-management-kit';\nimport type {\n ConnectionType,\n ConnectorCallResult,\n ConnectorDevice,\n ConnectorEventMap,\n ConnectorEventType,\n ConnectorSession,\n DeviceDescriptor,\n IConnector,\n TronSignMsgParams,\n UiResponseEvent,\n} from '@onekeyfe/hwk-adapter-core';\nimport type {\n BtcGetAddressCallParams,\n BtcGetPublicKeyCallParams,\n BtcSignMessageCallParams,\n BtcSignPsbtCallParams,\n BtcSignTransactionCallParams,\n EvmGetAddressCallParams,\n EvmSignMessageCallParams,\n EvmSignTransactionCallParams,\n EvmSignTypedDataCallParams,\n SolGetAddressCallParams,\n SolSignMessageCallParams,\n SolSignTransactionCallParams,\n TronGetAddressCallParams,\n TronSignMessageCallParams,\n TronSignTransactionCallParams,\n} from './chains';\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\n/**\n * A function that lazily loads and returns the transport factory\n * for the Ledger DMK builder (e.g. webHidTransportFactory, rnBleTransportFactory).\n */\nexport type TransportFactory = () => Promise<unknown>;\n\nexport interface LedgerConnectorBaseOptions {\n /**\n * Pre-built DMK instance. If not provided, a DMK will be created\n * lazily on first use via the transport factory.\n */\n dmk?: DeviceManagementKit;\n}\n\n// ---------------------------------------------------------------------------\n// Internal types\n// ---------------------------------------------------------------------------\n\ntype EventHandler<K extends ConnectorEventType> = (data: ConnectorEventMap[K]) => void;\n\n/**\n * Method-name prefix → Ledger app name. Keeps chain handlers free of\n * per-site `defaultAppName` boilerplate; `_ctxForMethod` injects it.\n */\nconst METHOD_PREFIX_TO_APP_NAME: Record<string, string> = {\n evm: 'Ethereum',\n btc: 'Bitcoin',\n sol: 'Solana',\n tron: 'Tron',\n};\n\nconst HARDWARE_ERROR_CODE_VALUES = new Set<number>(\n Object.values(HardwareErrorCode).filter((value): value is number => typeof value === 'number')\n);\n\n// Slow-advertising peripherals (screensaver, post-unpair) can advertise on\n// ~1s intervals, so the 800ms list-scan window is too tight at connect time.\nconst BLE_CONNECT_SCAN_TIMEOUT_MS = 1500;\n\n// ---------------------------------------------------------------------------\n// Default signer kit importer (webpack/rspack — uses \"exports\" field)\n// ---------------------------------------------------------------------------\n\n/**\n * Default importer for Ledger signer kit packages.\n * Uses bare module specifiers — works with bundlers that support \"exports\".\n * Metro (React Native) can't resolve these; pass a custom importer that\n * uses CJS paths (e.g. `@ledgerhq/device-signer-kit-ethereum/lib/cjs/index.js`).\n */\nasync function defaultLedgerKitImporter(pkg: string): Promise<any> {\n switch (pkg) {\n case '@ledgerhq/device-management-kit':\n return import('@ledgerhq/device-management-kit');\n case '@ledgerhq/device-signer-kit-ethereum':\n return import('@ledgerhq/device-signer-kit-ethereum');\n case '@ledgerhq/device-signer-kit-bitcoin':\n return import('@ledgerhq/device-signer-kit-bitcoin');\n case '@ledgerhq/device-signer-kit-solana':\n return import('@ledgerhq/device-signer-kit-solana');\n case '@ledgerhq/context-module':\n return import('@ledgerhq/context-module');\n default:\n throw new Error(`Unknown Ledger kit package: ${pkg}`);\n }\n}\n\n// Mirrors _getEthSigner in chains/evm.ts.\nasync function _getDeviceApps(ctx: ConnectorContext, sessionId: string): Promise<DeviceApps> {\n const manager = await ctx.getDeviceAppsManager();\n const apps = await manager.getOrCreate(sessionId);\n apps.onInteraction = (interaction: string) => {\n ctx.emit('ui-event', {\n type: collapseSignerInteraction(interaction),\n payload: { sessionId },\n });\n };\n apps.onRegisterCanceller = cancel => {\n ctx.registerCanceller(sessionId, cancel);\n };\n return apps;\n}\n\n// ---------------------------------------------------------------------------\n// LedgerConnectorBase\n// ---------------------------------------------------------------------------\n\n/**\n * Shared base class for Ledger IConnector implementations.\n *\n * Encapsulates all shared logic: device discovery, connection management,\n * method dispatch (EVM / BTC / SOL / TRON), signer lifecycle, event emission,\n * and error handling.\n *\n * Chain-specific method implementations live in `./chains/` and receive\n * a ConnectorContext that exposes shared helpers.\n *\n * Subclasses only need to:\n * 1. Supply a transport factory via the constructor.\n * 2. Optionally override `_resolveConnectId()` for transport-specific\n * device identity resolution.\n *\n * Invariant: one instance = one transport. `connectionType` is fixed at\n * construction. To switch transport (e.g. desktop BLE ↔ WebHID), the host\n * must build a new connector instance and replace the old one — don't add\n * multiple transports to a single instance. Lifting this constraint would\n * require routing `connectionType` from `descriptor.transport` per-device\n * and updating every `this.connectionType` branch in this file.\n */\nexport class LedgerConnectorBase implements IConnector {\n private _deviceManager: LedgerDeviceManager | null = null;\n\n private _signerManager: SignerManager | null = null;\n\n private _deviceAppsManager: DeviceAppsManager | null = null;\n\n private _dmk: DeviceManagementKit | null = null;\n\n private readonly _eventHandlers = new Map<\n ConnectorEventType,\n Set<EventHandler<ConnectorEventType>>\n >();\n\n private readonly _providedDmk: DeviceManagementKit | undefined;\n\n private readonly _createTransport: TransportFactory;\n\n public readonly connectionType: ConnectionType;\n\n // ---------------------------------------------------------------------------\n // Per-session DeviceAction cancellers\n //\n // Each chain handler registers its active DeviceAction's canceller via\n // ctx.registerCanceller(sessionId, cancel) and clears it on completion.\n // IConnector.cancel(sessionId) invokes the registered canceller, which\n // unsubscribes the observable and releases DMK's IntentQueue slot.\n // ---------------------------------------------------------------------------\n private readonly _cancellers = new Map<string, (reason?: CancelReason) => void>();\n\n // ---------------------------------------------------------------------------\n // Per-session DMK state subscriptions\n //\n // DMK only emits `device-disconnect` on the connector when `disconnect()`\n // is called explicitly. To pick up autonomous disconnects (USB unplug,\n // BLE drop, device sleep, DMK transport reset) we subscribe to\n // `_dmk.getDeviceSessionState({sessionId})` per active session and emit\n // `device-disconnect` ourselves the moment DMK reports the device went\n // to NOT_CONNECTED. The subscription is torn down on disconnect /\n // reset / observable completion to avoid leaks.\n // ---------------------------------------------------------------------------\n private readonly _sessionStateSubs = new Map<string, { unsubscribe: () => void }>();\n\n /**\n * Resolves a Ledger signer kit module by package name.\n * Override via constructor to use CJS paths for Metro (React Native).\n * Default: dynamic import with bare specifier (webpack/rspack).\n */\n protected _importLedgerKit: (pkg: string) => Promise<any>;\n\n /** Context object passed to per-chain handler functions. */\n private readonly _ctx: ConnectorContext;\n\n /** When true, BLE direct-connect throws NotAdvertising if the pre-flight\n * scan can't see the device — guard for GATT stacks that wedge on\n * non-advertising peripherals (iOS). */\n private readonly _requirePreFlightScan: boolean;\n\n constructor(\n createTransport: TransportFactory,\n options?: {\n connectionType?: ConnectionType;\n dmk?: DeviceManagementKit;\n /**\n * Override how `@ledgerhq/device-signer-kit-*` packages are imported.\n * Default: `(pkg) => import(pkg)` — works with webpack/rspack.\n * For Metro (React Native): pass a resolver that uses CJS paths.\n */\n importLedgerKit?: (pkg: string) => Promise<any>;\n /** Default false. RN-iOS subclass should pass `true`. */\n requirePreFlightScan?: boolean;\n }\n ) {\n this._createTransport = createTransport;\n this.connectionType = options?.connectionType ?? 'usb';\n this._providedDmk = options?.dmk;\n this._importLedgerKit = options?.importLedgerKit ?? defaultLedgerKitImporter;\n this._requirePreFlightScan = options?.requirePreFlightScan ?? false;\n if (this._providedDmk) {\n this._initManagers(this._providedDmk);\n }\n\n // Build the context that chain handlers use\n this._ctx = {\n emit: <K extends ConnectorEventType>(event: K, data: ConnectorEventMap[K]) =>\n this._emit(event, data),\n invalidateSession: sid => this._invalidateSession(sid),\n wrapError: (err, opts) => this._wrapError(err, opts),\n getOrCreateDmk: () => this._getOrCreateDmk(),\n getDeviceManager: () => this._getDeviceManager(),\n getSignerManager: () => this._getSignerManager(),\n getDeviceAppsManager: () => this._getDeviceAppsManager(),\n clearAllSigners: () => this._signerManager?.clearAll(),\n replaceSession: (oldSid, newSid) => this._replaceSession(oldSid, newSid),\n registerCanceller: (sid, cancel) => this._cancellers.set(sid, cancel),\n clearCanceller: sid => this._cancellers.delete(sid),\n importLedgerKit: this._importLedgerKit,\n };\n }\n\n // ---------------------------------------------------------------------------\n // Protected — hooks for subclasses\n // ---------------------------------------------------------------------------\n\n /**\n * Resolve the connectId for a discovered device descriptor.\n * Default: use the DMK path (ephemeral UUID).\n * Override in subclasses only when the public connectId differs from the transport path.\n */\n protected _resolveConnectId(descriptor: DeviceDescriptor): string {\n return descriptor.path;\n }\n\n /**\n * Authoritative discovery for this transport. Default = enumerate snapshot\n * (USB/HID). BLE overrides to drive from a live scan window since DMK's\n * enumerate() cache survives peripherals going offline.\n */\n protected async _discoverDescriptors(dm: LedgerDeviceManager): Promise<DeviceDescriptor[]> {\n let descriptors = await dm.enumerate();\n if (descriptors.length === 0) {\n try {\n await dm.requestDevice();\n } catch {\n // User may cancel the permission dialog\n }\n descriptors = await dm.enumerate();\n }\n return descriptors;\n }\n\n // ---------------------------------------------------------------------------\n // IConnector -- Device discovery\n //\n // Discovery never throws on multiple USB devices — it returns the full list.\n // The \"connect exactly one device\" rule is enforced upstream: an explicit\n // connectId connects that device (or fails as not-found), and only the\n // no-connectId USB path rejects when more than one device is present\n // (see LedgerAdapter._connectFirstOrSelect).\n // ---------------------------------------------------------------------------\n\n async searchDevices(): Promise<ConnectorDevice[]> {\n const dm = await this._getDeviceManager();\n\n const descriptors = await this._discoverDescriptors(dm);\n const resolvedDescriptors = descriptors.map(d => ({\n descriptor: d,\n connectId: this._resolveConnectId(d),\n }));\n const result: ConnectorDevice[] = resolvedDescriptors.map(({ descriptor: d, connectId }) => ({\n connectId,\n deviceId: d.path,\n name: d.name || d.type || 'Ledger',\n model: d.type,\n modelName: d.modelName,\n rssi: d.rssi,\n isConnectable: d.isConnectable,\n serialNumber: d.serialNumber,\n }));\n debugLog(\n `[DMK] connector.searchDevices() return count=${result.length} ids=[${result\n .map(r => r.connectId)\n .join(',')}] paths=[${result.map(r => r.deviceId).join(',')}]`\n );\n return result;\n }\n\n // ---------------------------------------------------------------------------\n // IConnector -- Connection\n // ---------------------------------------------------------------------------\n\n async connect(deviceId?: string): Promise<ConnectorSession> {\n // Trust caller's deviceId — search has already happened upstream\n // (UI scan flow). When caller didn't specify, fall back to a fresh\n // search so we have something to connect to.\n //\n // Only the explicit-connectId path gets the BLE direct-connect treatment.\n const callerSuppliedConnectId = Boolean(deviceId);\n let targetPath = deviceId;\n if (!targetPath) {\n const discovered = await this.searchDevices();\n if (discovered.length === 0) {\n throw new Error(\n `No Ledger device found. Make sure the device is connected${\n isLedgerBleConnectionType(this.connectionType)\n ? ' nearby with Bluetooth enabled'\n : ' via USB'\n } and unlocked.`\n );\n }\n targetPath = discovered[0].deviceId;\n }\n\n const externalConnectId = targetPath;\n\n // No active SMP timeout — let dm.connect resolve/reject naturally based\n // on what DMK / iOS BLE stack actually report. iOS has its own ~30s SMP\n // timeout; we trust it. The previous active 30s timer mis-judged slow-\n // but-successful pairings (user took 35s to confirm passkey).\n // 5min hang ceiling only catches genuine DMK stuck-promise (very rare).\n const HANG_CEILING_MS = 5 * 60_000;\n const dmConnectWithObserve = async (dm: LedgerDeviceManager, path: string): Promise<string> => {\n if (!isLedgerBleConnectionType(this.connectionType)) return dm.connect(path);\n\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n let timedOut = false;\n const connectPromise = dm.connect(path);\n const hangPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n timedOut = true;\n const err = new Error(\n `Ledger BLE connect did not return within ${\n HANG_CEILING_MS / 60_000\n }min — DMK hang fallback.`\n ) as Error & { _tag?: string; code?: number };\n err._tag = ERROR_TAG.BlePairingTimeout;\n err.code = HardwareErrorCode.BlePairingTimeout;\n reject(err);\n }, HANG_CEILING_MS);\n });\n try {\n return await Promise.race([connectPromise, hangPromise]);\n } catch (err) {\n const e = err as {\n _tag?: string;\n message?: string;\n errorCode?: unknown;\n statusCode?: unknown;\n originalError?: { _tag?: string; message?: string };\n };\n debugLog('[DMK] dm.connect rejected — observed:', {\n _tag: e?._tag,\n message: e?.message,\n errorCode: e?.errorCode,\n statusCode: e?.statusCode,\n originalTag: e?.originalError?._tag,\n originalMessage: e?.originalError?.message,\n });\n if (timedOut) {\n void connectPromise.then(\n sessionId => dm.disconnect(sessionId).catch(() => undefined),\n () => undefined\n );\n }\n throw err;\n } finally {\n if (timeoutId) clearTimeout(timeoutId);\n }\n };\n\n // Resolve dm lazily — _resetSignersAndSessions during retry replaces\n // _deviceManager, so capturing it in a closure would use a stale instance\n // whose _discovered Map has been disposed.\n // BLE direct-connect: caller supplied a connectId on a BLE transport.\n const isBleDirectConnect =\n isLedgerBleConnectionType(this.connectionType) && callerSuppliedConnectId;\n\n const throwNotAdvertising = (): never => {\n const err = new Error(\n 'Ledger device is not currently advertising. Wake up and unlock the device, keep it nearby, then try again.'\n ) as Error & { _tag?: string; code?: number };\n err._tag = ERROR_TAG.DeviceNotAdvertising;\n err.code = HardwareErrorCode.DeviceNotFound;\n throw err;\n };\n\n const doConnect = async (path: string): Promise<ConnectorSession> => {\n const dm = await this._getDeviceManager();\n // BLE direct-connect: refresh _discovered (DMK requires it before connect).\n // iOS throws early on empty scan to avoid the ~30s GATT/SMP wedge;\n // others trust the caller and let dm.connect() surface its own error.\n if (isBleDirectConnect && !dm.hasDiscoveredDevice(path)) {\n const live = await dm.getLiveDevices(BLE_CONNECT_SCAN_TIMEOUT_MS);\n if (this._requirePreFlightScan && !live.some(d => d.id === path)) {\n throwNotAdvertising();\n }\n }\n let sessionId: string;\n try {\n sessionId = await dmConnectWithObserve(dm, path);\n } catch (err) {\n // LedgerDeviceManager.connect() tags this when path isn't in _discovered.\n if (\n isBleDirectConnect &&\n (err as { _tag?: string } | null)?._tag === ERROR_TAG.DeviceNotInDiscoveryCache\n ) {\n throwNotAdvertising();\n }\n throw err;\n }\n try {\n this._watchSessionState(sessionId, externalConnectId);\n } catch (subErr) {\n // Subscription failure is fatal (see _watchSessionState) — disconnect\n // the just-created DMK session so connect()'s catch wraps it normally.\n debugLog('[DMK] state subscription failed during connect; disconnecting session:', subErr);\n try {\n await dm.disconnect(sessionId);\n } catch {\n // best-effort cleanup\n }\n throw subErr;\n }\n const info = dm.getDiscoveredDeviceInfo(path);\n const session: ConnectorSession = {\n sessionId,\n deviceInfo: {\n vendor: 'ledger',\n model: info?.model ?? 'unknown',\n modelName: info?.modelName,\n firmwareVersion: 'unknown',\n deviceId: path,\n connectId: externalConnectId,\n connectionType: this.connectionType,\n rssi: info?.rssi,\n capabilities: { persistentDeviceIdentity: false },\n },\n };\n // dm.connect() requires the descriptor in _discovered, so name lookup\n // will succeed; fallback covers any transient race.\n const name = dm.getDeviceName(path) ?? 'Ledger';\n this._emit('device-connect', {\n device: { connectId: externalConnectId, deviceId: path, name },\n });\n return session;\n };\n\n try {\n return await doConnect(targetPath);\n } catch (err) {\n // GATT failed — clean up local state and let the adapter own recovery.\n // We don't search-and-retry here: Layer 1 (`_doConnect` in LedgerAdapter)\n // is the single recovery owner. Doing a second doConnect here just\n // doubles the timeout the user sees before the unlock dialog appears.\n this._resetSignersAndSessions();\n\n // BLE GATT failures split into 3 tags:\n // BlePairingTimeout — our 30s timeout (pre-classified above)\n // BleGattBondingFailed — anything else (PeerRemoved / BleError /\n // iOS SMP reject / unknown transport)\n // DeviceNotAdvertising — pre-GATT scan miss (only from connectDevice)\n if (isLedgerBleConnectionType(this.connectionType)) {\n const tag = (err as { _tag?: string } | null | undefined)?._tag;\n\n // If DMK already gave a recognized tag (locked / disconnected / pairing\n // / transport-class), pass through untouched so SDK classifiers can\n // route on the real cause. We only wrap completely untagged errors.\n if (isKnownConnectionTag(tag)) {\n throw err;\n }\n\n // Untagged failure — wrap as BleGattBondingFailed so upstream still\n // has a code path. Original error preserved on `originalError`.\n const wrapped = new Error(\n 'Ledger Bluetooth pairing failed. Make sure the device is unlocked and nearby, then try again.'\n ) as Error & { _tag?: string; code?: number; originalError?: unknown };\n wrapped._tag = ERROR_TAG.BleGattBondingFailed;\n wrapped.code = HardwareErrorCode.BlePairingTimeout;\n wrapped.originalError = err;\n throw wrapped;\n }\n\n // USB/HID: typed errors flow through unchanged so APDU/transport\n // diagnostics aren't masked. Unknown failure → \"unplugged\".\n if (err && typeof err === 'object' && (err as { _tag?: string })._tag) {\n const taggedError =\n err instanceof Error\n ? err\n : Object.assign(\n new Error((err as { message?: string }).message ?? 'Ledger device error'),\n err\n );\n throw taggedError;\n }\n throw new Error('Ledger device appears unplugged. Plug in the device and try again.');\n }\n }\n\n async disconnect(sessionId: string): Promise<void> {\n if (!this._deviceManager) return;\n\n const deviceId = this._deviceManager.getDeviceId(sessionId);\n this._signerManager?.invalidate(sessionId);\n this._unwatchSessionState(sessionId);\n await this._deviceManager.disconnect(sessionId);\n\n if (deviceId) {\n this._emit('device-disconnect', { connectId: deviceId });\n }\n }\n\n /**\n * Subscribe to DMK's per-session state observable so that any autonomous\n * disconnect (USB unplug, BLE drop, device sleep, transport reset) is\n * surfaced as a `device-disconnect` event — without this, the upstream\n * `LedgerAdapter._sessions` map would hold a dead session entry until\n * the next call hit `DeviceSessionNotFound`.\n *\n * Subscribe failure is fatal — see the inline note at the subscribe call.\n */\n private _watchSessionState(sessionId: string, externalConnectId: string): void {\n const dmk = this._dmk;\n if (!dmk) return;\n const previous = this._sessionStateSubs.get(sessionId);\n if (previous) {\n try {\n previous.unsubscribe();\n } catch {\n // ignore\n }\n }\n // Subscribe failure is fatal: without this subscription we can't detect\n // autonomous disconnect (USB unplug, BLE drop, sleep), which leaks ghost\n // entries into the adapter's _sessions map and can route subsequent calls\n // to the wrong device. Let the error propagate so connect() cleans up the\n // just-created DMK session and fails loudly.\n const sub = dmk.getDeviceSessionState({ sessionId }).subscribe({\n next: (state: { deviceStatus?: string }) => {\n // String-compare against DeviceStatus.NOT_CONNECTED (\"NOT CONNECTED\")\n // to avoid pulling the runtime enum import (kept type-only for\n // Metro/RN compatibility — see _importLedgerKit).\n if (state?.deviceStatus === 'NOT CONNECTED') {\n this._handleAutonomousDisconnect(sessionId, externalConnectId);\n }\n },\n error: () => {\n // DMK closed the observable abnormally — treat as disconnect.\n this._handleAutonomousDisconnect(sessionId, externalConnectId);\n },\n complete: () => {\n // Observable completed — session is gone from DMK's POV.\n this._handleAutonomousDisconnect(sessionId, externalConnectId);\n },\n });\n this._sessionStateSubs.set(sessionId, sub);\n }\n\n private _unwatchSessionState(sessionId: string): void {\n const sub = this._sessionStateSubs.get(sessionId);\n if (!sub) return;\n try {\n sub.unsubscribe();\n } catch {\n // ignore\n }\n this._sessionStateSubs.delete(sessionId);\n }\n\n private _handleAutonomousDisconnect(sessionId: string, externalConnectId: string): void {\n if (!this._sessionStateSubs.has(sessionId)) return; // already handled\n debugLog(\n '[DMK] autonomous disconnect detected — sessionId:',\n sessionId,\n 'connectId:',\n externalConnectId\n );\n this._unwatchSessionState(sessionId);\n this._signerManager?.invalidate(sessionId);\n this._cancellers.get(sessionId)?.({\n code: HardwareErrorCode.DeviceDisconnected,\n tag: 'DeviceDisconnected',\n message: 'Device disconnected',\n });\n this._cancellers.delete(sessionId);\n this._emit('device-disconnect', { connectId: externalConnectId });\n }\n\n // ---------------------------------------------------------------------------\n // IConnector -- Method dispatch\n // ---------------------------------------------------------------------------\n\n // Device failures are returned as a `ConnectorCallResult` (success:false),\n // never thrown — so they cross the IHardwareBridge / extension offscreen↔SW\n // boundary as plain data instead of being mangled by the JsBridge error\n // whitelist (`toPlainError`). The SW-side adapter rehydrates and re-throws\n // locally (see LedgerAdapter._unwrapConnectorResult).\n async call(sessionId: string, method: string, params: unknown): Promise<ConnectorCallResult> {\n debugLog('[DMK] call:', method, JSON.stringify(params));\n try {\n const payload = await this._dispatch(sessionId, method, params);\n return { success: true, payload };\n } catch (err) {\n // True chain-app stuck (APDU 0x6901): user must back out of the\n // app on the device — keep the \"press both buttons to exit\" message.\n if (isAppStuckByApdu(err)) {\n return {\n success: false,\n error: serializeConnectorError(\n Object.assign(new Error('Ledger app is unresponsive'), {\n code: HardwareErrorCode.DeviceAppStuck,\n _tag: ERROR_TAG.DeviceAppStuck,\n originalError: err,\n })\n ),\n };\n }\n // DMK transport queue wedged (AlreadySendingApdu / UnknownDeviceExchange):\n // device + app are fine, only our SDK-side comms got tangled. Surface\n // as TransportError so the user sees a \"communication interrupted,\n // please retry\" message instead of a misleading \"exit app\" prompt.\n // Layer 2 (LedgerAdapter._runConnectorCall) will reset the connector\n // before re-throwing so the next call rebuilds a clean DMK instance.\n if (isTransportStuck(err)) {\n return {\n success: false,\n error: serializeConnectorError(\n Object.assign(new Error('Device communication interrupted, please retry'), {\n code: HardwareErrorCode.TransportError,\n _tag: ERROR_TAG.DeviceTransportStuck,\n originalError: err,\n })\n ),\n };\n }\n return { success: false, error: serializeConnectorError(err) };\n }\n }\n\n private async _dispatch(sessionId: string, method: string, params: unknown): Promise<unknown> {\n // Bind the chain's Ledger app name to ctx.wrapError once per dispatch so\n // chain handlers can call `ctx.wrapError(err)` with no per-site appName.\n const ctx = this._ctxForMethod(method);\n switch (method) {\n // EVM\n case 'evmGetAddress':\n return evmGetAddress(ctx, sessionId, params as EvmGetAddressCallParams);\n case 'evmSignTransaction':\n return evmSignTransaction(ctx, sessionId, params as EvmSignTransactionCallParams);\n case 'evmSignMessage':\n return evmSignMessage(ctx, sessionId, params as EvmSignMessageCallParams);\n case 'evmSignTypedData':\n return evmSignTypedData(ctx, sessionId, params as EvmSignTypedDataCallParams);\n // BTC\n case 'btcGetAddress':\n return btcGetAddress(ctx, sessionId, params as BtcGetAddressCallParams);\n case 'btcGetPublicKey':\n return btcGetPublicKey(ctx, sessionId, params as BtcGetPublicKeyCallParams);\n case 'btcSignTransaction':\n return btcSignTransaction(ctx, sessionId, params as BtcSignTransactionCallParams);\n case 'btcSignPsbt':\n return btcSignPsbt(ctx, sessionId, params as BtcSignPsbtCallParams);\n case 'btcSignMessage':\n return btcSignMessage(ctx, sessionId, params as BtcSignMessageCallParams);\n case 'btcGetMasterFingerprint':\n return btcGetMasterFingerprint(\n ctx,\n sessionId,\n params as { skipOpenApp?: boolean } | undefined\n );\n // SOL\n case 'solGetAddress':\n return solGetAddress(ctx, sessionId, params as SolGetAddressCallParams);\n case 'solSignTransaction':\n return solSignTransaction(ctx, sessionId, params as SolSignTransactionCallParams);\n case 'solSignMessage':\n return solSignMessage(ctx, sessionId, params as SolSignMessageCallParams);\n // TRON\n case 'tronGetAddress':\n return tronGetAddress(ctx, sessionId, params as TronGetAddressCallParams);\n case 'tronSignTransaction':\n return tronSignTransaction(ctx, sessionId, params as TronSignTransactionCallParams);\n case 'tronSignMessage': {\n // Explicit public→internal mapping so a field-name drift fails at\n // compile time, not silently at runtime (see bug: public `messageHex`\n // vs internal `messageHex` field name enforcement).\n const p = params as TronSignMsgParams;\n const internalParams: TronSignMessageCallParams = {\n path: p.path,\n messageHex: p.messageHex,\n };\n return tronSignMessage(ctx, sessionId, internalParams);\n }\n // OS-level device management — symmetric to chain handlers.\n // Each case uses try/catch/finally to mirror chain handlers: catch wraps\n // raw DMK errors (so mapLedgerError / isOutOfMemoryError run) and\n // invalidates the session (so a stale sid isn't reused by subsequent\n // listInstalledApps / signTransaction calls).\n case 'installApp': {\n const p = params as InstallAppCallParams;\n const apps = await _getDeviceApps(ctx, sessionId);\n try {\n // Progress callback is built here (not on params) so the function ref\n // never crosses the IHardwareBridge boundary. Emits as a `ui-event`\n // AppInstallProgress variant; the adapter re-keys sessionId →\n // connectId before re-emitting to its public typed emitter.\n return await apps.install(p.appName, ({ progress }) => {\n ctx.emit('ui-event', {\n type: EConnectorInteraction.AppInstallProgress,\n payload: {\n sessionId,\n appName: p.appName,\n progress,\n },\n });\n });\n } catch (err) {\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err);\n } finally {\n ctx.clearCanceller(sessionId);\n }\n }\n case 'listInstalledApps': {\n const apps = await _getDeviceApps(ctx, sessionId);\n try {\n return await apps.listInstalled(params as ListInstalledAppsCallParams);\n } catch (err) {\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err);\n } finally {\n ctx.clearCanceller(sessionId);\n }\n }\n case 'listInstalledNames': {\n const apps = await _getDeviceApps(ctx, sessionId);\n try {\n return await apps.listInstalledNames(params as ListInstalledAppsCallParams);\n } catch (err) {\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err);\n } finally {\n ctx.clearCanceller(sessionId);\n }\n }\n case 'listAvailableApps': {\n const apps = await _getDeviceApps(ctx, sessionId);\n try {\n return await apps.listAvailable();\n } catch (err) {\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err);\n } finally {\n ctx.clearCanceller(sessionId);\n }\n }\n case 'getFirmwareVersion': {\n const apps = await _getDeviceApps(ctx, sessionId);\n try {\n return await apps.getFirmwareVersion();\n } catch (err) {\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err);\n } finally {\n ctx.clearCanceller(sessionId);\n }\n }\n case 'getDeviceInfo': {\n const apps = await _getDeviceApps(ctx, sessionId);\n try {\n return await apps.getDeviceInfo();\n } catch (err) {\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err);\n } finally {\n ctx.clearCanceller(sessionId);\n }\n }\n default:\n throw new Error(`LedgerConnector: unknown method \"${method}\"`);\n }\n }\n\n async cancel(sessionId: string): Promise<void> {\n // Invoke the active DeviceAction canceller (registered by the chain handler).\n // This unsubscribes the observable and releases DMK's IntentQueue slot so\n // the next call on this session isn't blocked behind an orphaned intent.\n //\n // Note: Ledger devices have no hardware-level APDU abort. If the user has\n // an on-device confirmation prompt pending, it will remain until the user\n // presses Reject or the device times out.\n const cancel = this._cancellers.get(sessionId);\n if (cancel) {\n this._cancellers.delete(sessionId);\n try {\n cancel();\n } catch {\n // canceller may have already been invoked; ignore\n }\n }\n }\n\n uiResponse(_response: UiResponseEvent): void {\n // Ledger does not use interactive UI responses (PIN/passphrase)\n }\n\n // ---------------------------------------------------------------------------\n // IConnector -- Events\n // ---------------------------------------------------------------------------\n\n on<K extends ConnectorEventType>(event: K, handler: (data: ConnectorEventMap[K]) => void): void {\n if (!this._eventHandlers.has(event)) {\n this._eventHandlers.set(event, new Set());\n }\n this._eventHandlers.get(event)!.add(handler as EventHandler<ConnectorEventType>);\n }\n\n off<K extends ConnectorEventType>(event: K, handler: (data: ConnectorEventMap[K]) => void): void {\n this._eventHandlers.get(event)?.delete(handler as EventHandler<ConnectorEventType>);\n }\n\n // ---------------------------------------------------------------------------\n // IConnector -- Reset\n // ---------------------------------------------------------------------------\n\n reset(): void {\n this._resetAll();\n }\n\n // ---------------------------------------------------------------------------\n // Private -- DMK / Manager lifecycle\n // ---------------------------------------------------------------------------\n\n /**\n * Lazily create or return the DMK instance.\n * If a DMK was provided via constructor, it is used directly.\n * Otherwise, one is created via the transport factory.\n */\n protected async _getOrCreateDmk(): Promise<DeviceManagementKit> {\n debugLog(\n '[DMK] _getOrCreateDmk called, _dmk exists:',\n !!this._dmk,\n '_providedDmk exists:',\n !!this._providedDmk\n );\n if (this._dmk) return this._dmk;\n\n if (this._providedDmk) {\n this._dmk = this._providedDmk;\n return this._dmk;\n }\n\n const { DeviceManagementKitBuilder } = await this._importLedgerKit(\n '@ledgerhq/device-management-kit'\n );\n const transportFactory = await this._createTransport();\n\n debugLog('[DMK] _getOrCreateDmk: transportFactory type:', typeof transportFactory);\n\n const dmk: DeviceManagementKit = new DeviceManagementKitBuilder()\n .addTransport(transportFactory)\n .build();\n this._dmk = dmk;\n\n debugLog('[DMK] _getOrCreateDmk: DMK created');\n\n return dmk;\n }\n\n private _initManagers(dmk: DeviceManagementKit): void {\n this._dmk = dmk;\n this._deviceManager = new LedgerDeviceManager(dmk);\n\n // Pass a custom ETH signer builder that uses _importLedgerKit,\n // so the BLE connector's CJS override applies to ETH too.\n const importKit = this._importLedgerKit;\n this._signerManager = new SignerManager(dmk, async args => {\n const mod = await importKit('@ledgerhq/device-signer-kit-ethereum');\n return new mod.SignerEthBuilder(args);\n });\n this._deviceAppsManager = new DeviceAppsManager(dmk, importKit);\n }\n\n private async _getDeviceManager(): Promise<LedgerDeviceManager> {\n if (this._deviceManager) return this._deviceManager;\n\n const dmk = await this._getOrCreateDmk();\n this._initManagers(dmk);\n return this._deviceManager!;\n }\n\n private async _getSignerManager(): Promise<SignerManager> {\n if (!this._signerManager) {\n const dmk = await this._getOrCreateDmk();\n this._initManagers(dmk);\n }\n return this._signerManager!;\n }\n\n private async _getDeviceAppsManager(): Promise<DeviceAppsManager> {\n if (!this._deviceAppsManager) {\n const dmk = await this._getOrCreateDmk();\n this._initManagers(dmk);\n }\n return this._deviceAppsManager!;\n }\n\n private _invalidateSession(sessionId: string): void {\n this._signerManager?.invalidate(sessionId);\n }\n\n /**\n * Replace an old session with a new one after app switch.\n * Emits device-connect so the adapter updates its _sessions Map.\n */\n private _replaceSession(oldSessionId: string, _newSessionId: string): void {\n const dm = this._deviceManager;\n if (!dm) return;\n\n const oldDeviceId = dm.getDeviceId(oldSessionId);\n const connectId = oldDeviceId;\n\n // Invalidate old signer cache\n this._signerManager?.invalidate(oldSessionId);\n\n // Emit device-connect so the adapter picks up the new session\n if (connectId) {\n this._emit('device-connect', {\n device: {\n connectId,\n deviceId: connectId,\n name: 'Ledger',\n },\n });\n }\n }\n\n /**\n * Light reset: clear signer/session state but keep DMK alive.\n * Used by connect() retry — we want to re-discover with the same transport.\n *\n * Note: drops the device manager but tears down its RxJS subs first via\n * disposeKeepingDmk(). Bare null-assignment would leak _listenSub /\n * _discoverySub and double-scan after the next _initManagers().\n */\n private _resetSignersAndSessions(): void {\n debugLog('[DMK] _resetSignersAndSessions called');\n this._signerManager?.clearAll();\n this._signerManager = null;\n this._deviceAppsManager?.clearAll();\n this._deviceAppsManager = null;\n this._deviceManager?.disposeKeepingDmk();\n this._deviceManager = null;\n }\n\n private _resetAll(): void {\n debugLog('[DMK] _resetAll called');\n // Cancel any in-flight DeviceActions so their observables unsubscribe\n // and DMK's intent queues don't keep orphaned slots alive.\n for (const cancel of this._cancellers.values()) {\n try {\n cancel();\n } catch {\n // already cancelled / settled — ignore\n }\n }\n this._cancellers.clear();\n // Tear down per-session state subscriptions so we don't keep observing\n // a DMK we're about to drop.\n for (const sub of this._sessionStateSubs.values()) {\n try {\n sub.unsubscribe();\n } catch {\n // ignore\n }\n }\n this._sessionStateSubs.clear();\n this._signerManager?.clearAll();\n this._deviceAppsManager?.clearAll();\n this._deviceManager?.dispose();\n this._deviceManager = null;\n this._signerManager = null;\n this._deviceAppsManager = null;\n this._dmk = null;\n }\n\n // ---------------------------------------------------------------------------\n // Private -- Events\n // ---------------------------------------------------------------------------\n\n protected _emit<K extends ConnectorEventType>(event: K, data: ConnectorEventMap[K]): void {\n const handlers = this._eventHandlers.get(event);\n if (handlers) {\n for (const handler of handlers) {\n try {\n handler(data);\n } catch {\n // Don't let listener errors break the connector\n }\n }\n }\n }\n\n // ---------------------------------------------------------------------------\n // Private -- Error handling\n // ---------------------------------------------------------------------------\n\n /**\n * Return a per-call ctx with the chain's Ledger app name pre-bound to\n * wrapError, so chain handlers don't need to repeat `{ defaultAppName: 'X' }`\n * at every catch site. Falls through unchanged for unknown methods.\n */\n private _ctxForMethod(method: string): ConnectorContext {\n const prefix = /^(evm|btc|sol|tron)/.exec(method)?.[1];\n const defaultAppName = prefix ? METHOD_PREFIX_TO_APP_NAME[prefix] : undefined;\n if (!defaultAppName) return this._ctx;\n return {\n ...this._ctx,\n wrapError: (err, opts) => this._wrapError(err, { defaultAppName, ...opts }),\n };\n }\n\n private _wrapError(err: unknown, opts?: WrapErrorOptions): Error {\n const src = (err && typeof err === 'object' ? err : {}) as Record<string, unknown>;\n const hasSerializedCode =\n typeof src.code === 'number' && HARDWARE_ERROR_CODE_VALUES.has(src.code);\n const mapped = hasSerializedCode\n ? {\n code: src.code as HardwareErrorCode,\n message: typeof src.message === 'string' ? src.message : 'Unknown Ledger error',\n appName: typeof src.appName === 'string' ? src.appName : opts?.defaultAppName,\n }\n : mapLedgerError(err, opts);\n const error = new Error(mapped.message);\n // Preserve DMK / EthAppCommandError fields so downstream classifiers\n // (including cross-layer `wrapError` → caller re-classification) can still\n // key on APDU code and step context attached by deviceActionToPromise.\n Object.assign(error, {\n code: mapped.code,\n appName: mapped.appName,\n _tag: src._tag,\n errorCode: src.errorCode,\n _lastStep: src._lastStep,\n _deviceActionSteps: src._deviceActionSteps,\n });\n // Non-enumerable: DMK errors can carry APDU payloads / signing\n // intermediates that shouldn't leak into JSON.stringify / log transports.\n Object.defineProperty(error, 'originalError', {\n value: err,\n configurable: true,\n enumerable: false,\n writable: true,\n });\n return error;\n }\n}\n","import { ERROR_TAG } from '../errors';\nimport { debugError, debugLog } from '../utils/debugLog';\n\nimport type { DeviceChangeEvent, DeviceDescriptor } from '@onekeyfe/hwk-adapter-core';\nimport type { DeviceManagementKit } from '@ledgerhq/device-management-kit';\nimport type { DmkDiscoveredDevice } from '../types';\n\n/**\n * Manages device discovery, connection, and session tracking.\n * Wraps DMK's Observable APIs into simpler imperative calls.\n */\nexport class LedgerDeviceManager {\n private readonly _dmk: DeviceManagementKit;\n\n private readonly _discovered = new Map<string, DmkDiscoveredDevice>();\n\n private readonly _sessions = new Map<string, string>(); // deviceId → sessionId\n\n private readonly _sessionToDevice = new Map<string, string>(); // sessionId → deviceId\n\n private _listenSub: { unsubscribe: () => void } | null = null;\n\n constructor(dmk: DeviceManagementKit) {\n this._dmk = dmk;\n }\n\n /**\n * One-shot enumeration: subscribe to listenToAvailableDevices,\n * take the first emission, unsubscribe, return DeviceDescriptors.\n */\n enumerate(): Promise<DeviceDescriptor[]> {\n debugLog('[DMK] enumerate() called, dmk exists:', !!this._dmk);\n return new Promise<DeviceDescriptor[]>(resolve => {\n let resolved = false;\n let syncResult: DmkDiscoveredDevice[] | null = null;\n let sub: { unsubscribe: () => void } | null = null;\n\n sub = this._dmk.listenToAvailableDevices({}).subscribe({\n next: devices => {\n if (resolved) return;\n resolved = true;\n this._discovered.clear();\n debugLog(\n `[DMK] enumerate count=${devices.length} ids=[${devices.map(d => d.id).join(',')}]`\n );\n for (const d of devices) {\n this._discovered.set(d.id, d);\n }\n // If sub is already assigned (async emission), resolve and unsubscribe immediately\n if (sub) {\n sub.unsubscribe();\n resolve(\n devices.map(d => ({\n path: d.id,\n type: d.deviceModel.model,\n modelName: d.deviceModel.name,\n name: d.name,\n transport: d.transport,\n rssi: d.rssi,\n }))\n );\n } else {\n // Synchronous emission — sub not yet assigned, defer to after subscribe()\n syncResult = devices;\n }\n },\n error: () => {\n if (!resolved) {\n resolved = true;\n resolve([]);\n }\n },\n });\n\n // If BehaviorSubject fired synchronously, sub is now assigned\n if (syncResult !== null) {\n sub.unsubscribe();\n const devices = syncResult as DmkDiscoveredDevice[];\n resolve(\n devices.map(d => ({\n path: d.id,\n type: d.deviceModel.model,\n modelName: d.deviceModel.name,\n name: d.name,\n transport: d.transport,\n rssi: d.rssi,\n }))\n );\n }\n });\n }\n\n /**\n * Continuous listening: tracks device connect/disconnect via diffing.\n */\n listen(onChange: (event: DeviceChangeEvent) => void): void {\n this.stopListening();\n let previousIds = new Set<string>();\n\n this._listenSub = this._dmk.listenToAvailableDevices({}).subscribe({\n next: devices => {\n const currentIds = new Set(devices.map(d => d.id));\n\n for (const d of devices) {\n this._discovered.set(d.id, d);\n debugLog('[DMK] listen device:', d.id, d.name);\n if (!previousIds.has(d.id)) {\n onChange({\n type: 'device-connected',\n descriptor: {\n path: d.id,\n type: d.deviceModel.model,\n modelName: d.deviceModel.name,\n name: d.name,\n transport: d.transport,\n rssi: d.rssi,\n },\n });\n }\n }\n for (const id of previousIds) {\n if (!currentIds.has(id)) {\n this._discovered.delete(id);\n onChange({ type: 'device-disconnected', descriptor: { path: id } });\n }\n }\n previousIds = currentIds;\n },\n });\n }\n\n stopListening(): void {\n this._listenSub?.unsubscribe();\n this._listenSub = null;\n }\n\n /**\n * Resolve to the latest snapshot of advertising devices observed within\n * `timeoutMs`. Rewrites `_discovered` so it tracks the live list.\n *\n * `listenToAvailableDevices` is a BehaviorSubject — it emits the cached\n * list on subscribe and *only* re-emits when the list changes. A stable\n * list of currently-advertising devices therefore produces only the\n * subscription frame; treating that frame as \"fossil to be discarded\"\n * caused devices to flicker in/out of the UI as searches alternated\n * between \"saw a change frame\" and \"saw only the cached frame\".\n *\n * The window still gives a chance for the active scan to update the list\n * (e.g. drop a peripheral that just stopped broadcasting), but if nothing\n * changes we trust the snapshot — DMK silence on a stable list means\n * \"everything's still there\".\n */\n getLiveDevices(timeoutMs = 1500): Promise<DmkDiscoveredDevice[]> {\n debugLog(`[DMK] getLiveDevices() called, timeoutMs=${timeoutMs}`);\n // Ensure a discovery is in flight; no-op if already scanning.\n void this.requestDevice();\n\n return new Promise<DmkDiscoveredDevice[]>(resolve => {\n let done = false;\n let lastSeen: DmkDiscoveredDevice[] = [];\n let sub: { unsubscribe: () => void } | null = null;\n\n const finish = (devices: DmkDiscoveredDevice[]) => {\n if (done) return;\n done = true;\n sub?.unsubscribe();\n clearTimeout(timer);\n this._discovered.clear();\n for (const d of devices) this._discovered.set(d.id, d);\n debugLog(\n `[DMK] getLiveDevices() resolved count=${devices.length} ids=[${devices\n .map(d => d.id)\n .join(',')}]`\n );\n resolve(devices);\n };\n\n // On timeout, accept whatever we last saw.\n const timer = setTimeout(() => finish(lastSeen), timeoutMs);\n\n sub = this._dmk.listenToAvailableDevices({}).subscribe({\n next: devices => {\n lastSeen = devices;\n },\n error: err => {\n debugError('[DMK] getLiveDevices() error:', err);\n finish(lastSeen);\n },\n complete: () => finish(lastSeen),\n });\n });\n }\n\n /**\n * Trigger browser device selection (WebHID requestDevice).\n * Starts discovery for a short period, then stops.\n */\n /**\n * Start BLE discovery if not already running.\n * Does NOT stop — DMK keeps scanning in the background so that\n * listenToAvailableDevices() always has fresh data.\n */\n private _discoverySub: { unsubscribe: () => void } | null = null;\n\n requestDevice(): Promise<void> {\n if (this._discoverySub) {\n // Already scanning\n return Promise.resolve();\n }\n debugLog('[DMK] requestDevice() starting persistent BLE scan');\n this._discoverySub = this._dmk.startDiscovering({}).subscribe({\n next: d => {\n debugLog('[DMK] BLE discovered:', d.name || d.id);\n this._discovered.set(d.id, d);\n },\n error: err => {\n debugError('[DMK] BLE scan error:', err);\n this._discoverySub = null;\n },\n });\n return Promise.resolve();\n }\n\n /** Lookup a previously-discovered device's display name. */\n getDeviceName(deviceId: string): string | undefined {\n return this._discovered.get(deviceId)?.name;\n }\n\n /** Lookup minimal model/signal info from a previously-discovered device. */\n getDiscoveredDeviceInfo(\n deviceId: string\n ): { model?: string; modelName?: string; name?: string; rssi?: number | null } | undefined {\n const d = this._discovered.get(deviceId);\n if (!d) return undefined;\n return {\n model: d.deviceModel?.model,\n modelName: d.deviceModel?.name,\n name: d.name,\n rssi: d.rssi,\n };\n }\n\n hasDiscoveredDevice(deviceId: string): boolean {\n return this._discovered.has(deviceId);\n }\n\n /** Connect to a previously discovered device. Returns sessionId. */\n async connect(deviceId: string): Promise<string> {\n const device = this._discovered.get(deviceId);\n if (!device) {\n const err = new Error(\n `Device \"${deviceId}\" not found in discovery cache. Call enumerate() or listen() first.`\n ) as Error & { _tag?: string };\n err._tag = ERROR_TAG.DeviceNotInDiscoveryCache;\n throw err;\n }\n const sessionId = await this._dmk.connect({ device });\n this._sessions.set(deviceId, sessionId);\n this._sessionToDevice.set(sessionId, deviceId);\n return sessionId;\n }\n\n /** Disconnect a session. */\n async disconnect(sessionId: string): Promise<void> {\n await this._dmk.disconnect({ sessionId });\n const deviceId = this._sessionToDevice.get(sessionId);\n if (deviceId) this._sessions.delete(deviceId);\n this._sessionToDevice.delete(sessionId);\n }\n\n getSessionId(deviceId: string): string | undefined {\n return this._sessions.get(deviceId);\n }\n\n getDeviceId(sessionId: string): string | undefined {\n return this._sessionToDevice.get(sessionId);\n }\n\n /** Get the underlying DMK instance (needed by SignerManager). */\n getDmk(): DeviceManagementKit {\n return this._dmk;\n }\n\n stopDiscovery(): void {\n if (this._discoverySub) {\n this._discoverySub.unsubscribe();\n this._discoverySub = null;\n this._dmk.stopDiscovering();\n }\n }\n\n dispose(): void {\n this.stopListening();\n this.stopDiscovery();\n this._discovered.clear();\n this._sessions.clear();\n this._sessionToDevice.clear();\n this._dmk.close();\n }\n\n /**\n * Tear down RxJS subscriptions and local state without closing the DMK.\n * For light-reset paths that want to drop session state but keep the\n * underlying transport alive for retry. Call this instead of orphaning\n * the manager — bare null assignment leaks _listenSub / _discoverySub.\n */\n disposeKeepingDmk(): void {\n this.stopListening();\n this.stopDiscovery();\n this._discovered.clear();\n this._sessions.clear();\n this._sessionToDevice.clear();\n }\n}\n","import { SignerEthBuilder } from '@ledgerhq/device-signer-kit-ethereum';\nimport { ContextModuleBuilder } from '@ledgerhq/context-module';\n\nimport { SignerEth } from './SignerEth';\nimport { debugLog } from '../utils/debugLog';\n\nimport type { DeviceManagementKit } from '@ledgerhq/device-management-kit';\nimport type { SignerEth as ISdkSignerEth } from '@ledgerhq/device-signer-kit-ethereum';\nimport type { ContextModule } from '@ledgerhq/context-module';\n\ntype SignerEthBuilderFn = (args: { dmk: DeviceManagementKit; sessionId: string }) =>\n | {\n withContextModule?(contextModule: ContextModule): { build(): ISdkSignerEth };\n build(): ISdkSignerEth;\n }\n | Promise<{\n withContextModule?(contextModule: ContextModule): { build(): ISdkSignerEth };\n build(): ISdkSignerEth;\n }>;\n\n/**\n * Per-sessionId SignerEth factory. Builds fresh on every call — DMK signers\n * hold DeviceAction state that isn't safe to reuse, so `invalidate` /\n * `clearAll` are kept as no-op lifecycle hooks for callers.\n */\nexport class SignerManager {\n private readonly _dmk: DeviceManagementKit;\n\n private readonly _builderFn: SignerEthBuilderFn;\n\n constructor(dmk: DeviceManagementKit, builderFn?: SignerEthBuilderFn) {\n this._dmk = dmk;\n this._builderFn = builderFn ?? SignerManager._defaultBuilder();\n }\n\n async getOrCreate(sessionId: string): Promise<SignerEth> {\n debugLog('[DMK] SignerManager.getOrCreate:', { sessionId });\n const builder = await this._builderFn({ dmk: this._dmk, sessionId });\n const builderWithContext = builder.withContextModule\n ? builder.withContextModule(SignerManager._createContextModule())\n : builder;\n return new SignerEth(builderWithContext.build());\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars, class-methods-use-this\n invalidate(_sessionId: string): void {}\n\n // eslint-disable-next-line class-methods-use-this\n clearAll(): void {}\n\n private static _defaultBuilder(): SignerEthBuilderFn {\n return args => new SignerEthBuilder(args);\n }\n\n private static _createContextModule(): ContextModule {\n const contextModule = new ContextModuleBuilder({}).removeDefaultLoaders().build();\n return SignerManager.wrapBlindSigningReportNonBlocking(contextModule);\n }\n\n static wrapBlindSigningReportNonBlocking<T extends ContextModule>(contextModule: T): T {\n const report = contextModule.report.bind(contextModule);\n contextModule.report = async params => {\n try {\n void report(params).catch(err => {\n debugLog('[DMK] ContextModule.report failed:', err);\n });\n } catch (err) {\n debugLog('[DMK] ContextModule.report failed:', err);\n }\n };\n return contextModule;\n }\n}\n","import { hexToBytes } from '@onekeyfe/hwk-adapter-core';\n\nimport { deviceActionToPromise } from './deviceActionToPromise';\nimport { debugLog } from '../utils/debugLog';\n\nimport type { CancelReason } from './deviceActionToPromise';\nimport type { SignerEth as ISdkSignerEth, TypedData } from '@ledgerhq/device-signer-kit-ethereum';\nimport type { SignerEvmAddress, SignerEvmSignature } from '../types';\n\n/** Timeout for user-interactive operations (verify address, sign). */\nconst INTERACTIVE_TIMEOUT_MS = 5 * 60_000;\n\n/**\n * Wraps Ledger's SDK signer (Observable-based DeviceActions) into\n * a simple async interface returning plain serializable data.\n */\nexport class SignerEth {\n onInteraction?: (interaction: string) => void;\n\n // eslint-disable-next-line no-useless-constructor, no-empty-function\n constructor(private readonly _sdk: ISdkSignerEth) {}\n\n /**\n * Optional callback registered per-call so the caller can obtain a canceller\n * for the underlying DeviceAction. Caller can invoke it to release DMK's\n * IntentQueue slot and unsubscribe from the action's observable.\n */\n onRegisterCanceller?: (cancel: (reason?: CancelReason) => void) => void;\n\n async getAddress(\n derivationPath: string,\n options?: { checkOnDevice?: boolean }\n ): Promise<SignerEvmAddress> {\n const checkOnDevice = options?.checkOnDevice ?? false;\n debugLog('[DMK] getAddress → DMK:', { derivationPath, checkOnDevice });\n const action = this._sdk.getAddress(derivationPath, {\n checkOnDevice,\n });\n // checkOnDevice needs user interaction → long timeout; otherwise default 30s\n const timeout = checkOnDevice ? INTERACTIVE_TIMEOUT_MS : undefined;\n return deviceActionToPromise<SignerEvmAddress>(\n action,\n this.onInteraction,\n timeout,\n this.onRegisterCanceller\n );\n }\n\n async signTransaction(\n derivationPath: string,\n serializedTxHex: string\n ): Promise<SignerEvmSignature> {\n const action = this._sdk.signTransaction(derivationPath, hexToBytes(serializedTxHex));\n return deviceActionToPromise<SignerEvmSignature>(\n action,\n this.onInteraction,\n INTERACTIVE_TIMEOUT_MS,\n this.onRegisterCanceller\n );\n }\n\n async signMessage(derivationPath: string, message: string): Promise<SignerEvmSignature> {\n // DMK treats string as ASCII text (addAsciiStringToData), but we receive\n // hex-encoded message bytes. Decode to Uint8Array so DMK uses\n // addBufferToData — matching the OneKey SDK's behavior.\n const action = this._sdk.signMessage(derivationPath, hexToBytes(message));\n return deviceActionToPromise<SignerEvmSignature>(\n action,\n this.onInteraction,\n INTERACTIVE_TIMEOUT_MS,\n this.onRegisterCanceller\n );\n }\n\n async signTypedData(derivationPath: string, data: TypedData): Promise<SignerEvmSignature> {\n const action = this._sdk.signTypedData(derivationPath, data);\n return deviceActionToPromise<SignerEvmSignature>(\n action,\n this.onInteraction,\n INTERACTIVE_TIMEOUT_MS,\n this.onRegisterCanceller\n );\n }\n}\n","import { DeviceActionStatus } from '@ledgerhq/device-management-kit';\n\nimport { debugLog } from '../utils/debugLog';\n\nimport type { DeviceAction, DeviceActionState } from '../types';\n\n/**\n * Idle watchdog: fires iff transport wedged (no DMK emission).\n * 65s > DMK's own 60s waitForDeviceUnlock — DMK fires first in normal\n * cases; we only catch the case where DMK itself is stuck.\n * Paused during interactive pending.\n */\nconst IDLE_WATCHDOG_MS = 65_000;\n\n/** Optional context attached to the rejection when a canceller fires. */\nexport interface CancelReason {\n code?: number;\n tag?: string;\n message?: string;\n}\n\n/**\n * Convert a DMK DeviceAction (Observable-based) into a Promise.\n * Handles pending -> completed/error state transitions and interaction callbacks.\n *\n * Tracks the last DMK step observed (e.g. `signer.eth.steps.blindSignTransactionFallback`)\n * and attaches it to the rejected error as a non-enumerable `_lastStep` property,\n * so upstream error classifiers can distinguish failure contexts (e.g. Blind signing\n * disabled vs. generic Invalid data).\n *\n * @param timeoutMs Idle watchdog ms. Re-armed on each emission, paused\n * during interactive pending. 0 disables. Default 65s\n * (covers DMK's 60s + margin; we're a backstop only).\n * @param onRegisterCanceller Optional callback that receives a function which, when\n * called, unsubscribes and cancels the underlying DeviceAction\n * (releases DMK's IntentQueue slot). Caller is responsible\n * for invoking the canceller on timeout/abort scenarios.\n */\nexport function deviceActionToPromise<T>(\n action: DeviceAction<T>,\n onInteraction?: (interaction: string) => void,\n timeoutMs: number = IDLE_WATCHDOG_MS,\n onRegisterCanceller?: (cancel: (reason?: CancelReason) => void) => void,\n onIntermediate?: (intermediateValue: unknown) => void\n): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n let settled = false;\n let lastStep: string | undefined;\n let activeInteraction: string | undefined;\n const observedSteps: string[] = [];\n // eslint-disable-next-line prefer-const -- assigned once after declaration, but must be declared before use in cleanup\n let sub: { unsubscribe: () => void };\n let timer: ReturnType<typeof setTimeout> | null = null;\n\n /** Fully tear down this action: unsubscribe + release DMK intent queue slot. */\n const cancelAction = () => {\n try {\n sub?.unsubscribe();\n } catch {\n // Subscription may already be closed.\n }\n try {\n action.cancel();\n } catch {\n // DMK action may already be settled.\n }\n };\n\n const clearActiveInteraction = () => {\n if (activeInteraction) {\n debugLog(\n '[DeviceAction] requiredUserInteraction',\n 'interaction=none',\n `prev=${activeInteraction}`,\n `step=${lastStep ?? 'unknown'}`\n );\n activeInteraction = undefined;\n onInteraction?.('interaction-complete');\n return true;\n }\n return false;\n };\n\n const emitInteraction = (interaction: unknown) => {\n if (!onInteraction) {\n return;\n }\n\n if (!interaction || interaction === 'none') {\n clearActiveInteraction();\n return;\n }\n\n const interactionName = String(interaction);\n if (interactionName === activeInteraction) {\n return;\n }\n\n activeInteraction = interactionName;\n debugLog(\n '[DeviceAction] requiredUserInteraction',\n `interaction=${interactionName}`,\n `step=${lastStep ?? 'unknown'}`\n );\n // unlock-device is DMK's own bounded poll. Other interaction\n // states keep the caller-provided watchdog so a stuck observable\n // cannot hold the queue slot forever.\n if (interaction === 'unlock-device' && timer) {\n clearTimeout(timer);\n timer = null;\n }\n onInteraction(interactionName);\n };\n\n const completeInteraction = () => {\n if (!clearActiveInteraction()) {\n onInteraction?.('interaction-complete');\n }\n };\n\n const armIdleWatchdog = () => {\n if (timer) clearTimeout(timer);\n if (timeoutMs > 0) {\n timer = setTimeout(() => {\n if (!settled) {\n settled = true;\n completeInteraction();\n cancelAction();\n reject(\n new Error(\n 'Ledger transport unresponsive: no DMK state change within the watchdog window. The device may have lost connection.'\n )\n );\n }\n }, timeoutMs);\n }\n };\n\n armIdleWatchdog();\n\n // Expose a canceller for external abort. Optional reason tags the rejection.\n if (onRegisterCanceller) {\n onRegisterCanceller(reason => {\n if (settled) {\n return;\n }\n settled = true;\n if (timer) clearTimeout(timer);\n completeInteraction();\n cancelAction();\n const err = new Error(reason?.message ?? 'Device action cancelled');\n if (reason?.code !== undefined) {\n (err as Error & { code?: number }).code = reason.code;\n }\n if (reason?.tag) {\n Object.defineProperty(err, '_tag', {\n value: reason.tag,\n configurable: true,\n enumerable: false,\n writable: true,\n });\n }\n reject(err);\n });\n }\n\n sub = action.observable.subscribe({\n next: (state: DeviceActionState<T>) => {\n // Drop post-settle emissions to avoid leaking the watchdog.\n if (settled) {\n return;\n }\n armIdleWatchdog();\n\n // Track last DMK step so caller can disambiguate failure contexts\n // (e.g. 0x6a80 during blindSignTransactionFallback = Blind signing disabled)\n const step = (state as { intermediateValue?: { step?: string } })?.intermediateValue?.step;\n if (step) {\n lastStep = step;\n if (observedSteps[observedSteps.length - 1] !== step) {\n observedSteps.push(step);\n }\n }\n\n if (state.status === DeviceActionStatus.Completed) {\n settled = true;\n if (timer) clearTimeout(timer);\n completeInteraction();\n sub?.unsubscribe();\n resolve(state.output);\n } else if (state.status === DeviceActionStatus.Error) {\n settled = true;\n if (timer) clearTimeout(timer);\n completeInteraction();\n sub?.unsubscribe();\n rejectWithStepContext(state.error, lastStep, observedSteps, reject);\n } else if (state.status === DeviceActionStatus.Pending) {\n if (onIntermediate) {\n try {\n onIntermediate(state.intermediateValue);\n } catch {\n // listener errors must not abort the device action\n }\n }\n if (onInteraction) {\n const interaction = state.intermediateValue?.requiredUserInteraction;\n emitInteraction(interaction);\n }\n }\n },\n error: (err: unknown) => {\n if (!settled) {\n settled = true;\n if (timer) clearTimeout(timer);\n completeInteraction();\n sub?.unsubscribe();\n rejectWithStepContext(err, lastStep, observedSteps, reject);\n }\n },\n complete: () => {\n if (!settled) {\n settled = true;\n if (timer) clearTimeout(timer);\n completeInteraction();\n reject(new Error('Device action completed without result'));\n }\n },\n });\n });\n}\n\n/**\n * Reject with the DMK error after annotating observed step context. These\n * fields are non-enumerable so they do not pollute JSON.stringify / log\n * output, but classifiers can still read them.\n */\nfunction rejectWithStepContext(\n err: unknown,\n lastStep: string | undefined,\n observedSteps: string[],\n reject: (reason: unknown) => void\n): void {\n if (err && typeof err === 'object' && (lastStep || observedSteps.length > 0)) {\n try {\n if (lastStep) {\n Object.defineProperty(err, '_lastStep', {\n value: lastStep,\n configurable: true,\n enumerable: false,\n writable: true,\n });\n }\n if (observedSteps.length > 0) {\n Object.defineProperty(err, '_deviceActionSteps', {\n value: [...observedSteps],\n configurable: true,\n enumerable: false,\n writable: true,\n });\n }\n } catch {\n // Frozen error objects — give up, classifier will fall back.\n }\n }\n reject(err);\n}\n","import { HardwareErrorCode, padHex64, stripHex } from '@onekeyfe/hwk-adapter-core';\n\nimport { collapseSignerInteraction, normalizePath } from './utils';\nimport { debugLog } from '../../utils/debugLog';\n\nimport type { TypedData } from '@ledgerhq/device-signer-kit-ethereum';\nimport type { SignerEvmSignature } from '../../types';\nimport type { ConnectorContext } from './types';\n\n// ---------------------------------------------------------------------------\n// Call param types\n// ---------------------------------------------------------------------------\n\nexport interface EvmGetAddressCallParams {\n path: string;\n showOnDevice?: boolean;\n}\n\nexport interface EvmSignTransactionCallParams {\n path: string;\n /** RLP-serialized transaction hex (0x-prefixed or plain) */\n serializedTx?: string;\n}\n\nexport interface EvmSignMessageCallParams {\n path: string;\n message: string;\n}\n\nexport interface EvmSignTypedDataCallParams {\n path: string;\n data: TypedData;\n mode?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Handler\n// ---------------------------------------------------------------------------\n\nexport async function evmGetAddress(\n ctx: ConnectorContext,\n sessionId: string,\n params: EvmGetAddressCallParams\n): Promise<{ address: string; publicKey?: string }> {\n const signer = await _getEthSigner(ctx, sessionId);\n const path = normalizePath(params.path);\n const checkOnDevice = params.showOnDevice ?? false;\n debugLog('[DMK] evmGetAddress -> signer.getAddress:', { path, checkOnDevice });\n\n try {\n const result = await signer.getAddress(path, { checkOnDevice });\n return { address: result.address, publicKey: result.publicKey };\n } catch (err) {\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err);\n } finally {\n ctx.clearCanceller(sessionId);\n }\n}\n\nexport async function evmSignTransaction(\n ctx: ConnectorContext,\n sessionId: string,\n params: EvmSignTransactionCallParams\n): Promise<{ v: string; r: string; s: string }> {\n if (!params.serializedTx) {\n throw Object.assign(\n new Error(\n 'Ledger requires a pre-serialized transaction (serializedTx). Provide an RLP-encoded hex string.'\n ),\n { code: HardwareErrorCode.InvalidParams }\n );\n }\n\n const signer = await _getEthSigner(ctx, sessionId);\n const path = normalizePath(params.path);\n\n try {\n const result: SignerEvmSignature = await signer.signTransaction(path, params.serializedTx);\n return {\n v: `0x${result.v.toString(16)}`,\n r: padHex64(result.r),\n s: padHex64(result.s),\n };\n } catch (err) {\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err);\n } finally {\n ctx.clearCanceller(sessionId);\n }\n}\n\nexport async function evmSignMessage(\n ctx: ConnectorContext,\n sessionId: string,\n params: EvmSignMessageCallParams\n): Promise<{ signature: string }> {\n const signer = await _getEthSigner(ctx, sessionId);\n const path = normalizePath(params.path);\n\n try {\n const result: SignerEvmSignature = await signer.signMessage(path, params.message);\n const rHex = stripHex(result.r).padStart(64, '0');\n const sHex = stripHex(result.s).padStart(64, '0');\n const vHex = result.v.toString(16).padStart(2, '0');\n return { signature: `0x${rHex}${sHex}${vHex}` };\n } catch (err) {\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err);\n } finally {\n ctx.clearCanceller(sessionId);\n }\n}\n\nexport async function evmSignTypedData(\n ctx: ConnectorContext,\n sessionId: string,\n params: EvmSignTypedDataCallParams\n): Promise<{ signature: string }> {\n if (params.mode === 'hash') {\n throw Object.assign(\n new Error(\n 'Ledger does not support hash-only EIP-712 signing. Use mode \"full\" with the complete typed data structure.'\n ),\n { code: HardwareErrorCode.MethodNotSupported }\n );\n }\n\n const signer = await _getEthSigner(ctx, sessionId);\n const path = normalizePath(params.path);\n\n try {\n const result: SignerEvmSignature = await signer.signTypedData(path, params.data);\n const rHex = stripHex(result.r).padStart(64, '0');\n const sHex = stripHex(result.s).padStart(64, '0');\n const vHex = result.v.toString(16).padStart(2, '0');\n return { signature: `0x${rHex}${sHex}${vHex}` };\n } catch (err) {\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err);\n } finally {\n ctx.clearCanceller(sessionId);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Internal — ETH signer creation\n// ---------------------------------------------------------------------------\n\nasync function _getEthSigner(ctx: ConnectorContext, sessionId: string) {\n const signerManager = await ctx.getSignerManager();\n const signer = await signerManager.getOrCreate(sessionId);\n\n // Wire up interaction events (open-app, unlock, verify-address, sign, etc.)\n // DMK-specific values (verify-address, sign-transaction, sign-typed-data,\n // sign-personal-message) collapse to ConfirmOnDevice via the helper.\n signer.onInteraction = (interaction: string) => {\n debugLog('[LedgerConnector] evm.onInteraction:', interaction);\n ctx.emit('ui-event', {\n type: collapseSignerInteraction(interaction),\n payload: { sessionId },\n });\n };\n\n // Expose DeviceAction canceller to the connector so that cancel(sessionId)\n // can release DMK's intent queue slot and unsubscribe cleanly.\n signer.onRegisterCanceller = cancel => {\n ctx.registerCanceller(sessionId, cancel);\n };\n\n return signer;\n}\n","import { EConnectorInteraction } from '@onekeyfe/hwk-adapter-core';\n\n/**\n * Strip the \"m/\" prefix from BIP-44 derivation paths.\n * Ledger DMK requires paths without the \"m/\" prefix.\n */\nexport function normalizePath(path: string): string {\n return path.startsWith('m/') ? path.slice(2) : path;\n}\n\n/**\n * Collapse Ledger DMK's raw `requiredUserInteraction` strings into the\n * subset of EConnectorInteraction variants that share the simple\n * `{ sessionId }` payload shape — used by chain-signer emit sites.\n *\n * DMK emits chain-signer-specific strings like \"verify-address\",\n * \"sign-transaction\", \"sign-typed-data\", \"sign-personal-message\" — they\n * all mean \"the user must act on the device screen\", i.e. ConfirmOnDevice\n * per the public ConnectorUiEvent type contract. Leaking raw DMK strings\n * out of the SDK would break consumers that switch on EConnectorInteraction.\n *\n * Note: AppInstallProgress and Searching are NOT in the return type — they\n * carry richer payloads and are emitted from dedicated call sites.\n */\nexport type CollapsedSignerInteraction =\n | EConnectorInteraction.ConfirmOpenApp\n | EConnectorInteraction.UnlockDevice\n | EConnectorInteraction.InteractionComplete\n | EConnectorInteraction.ConfirmOnDevice;\n\nexport function collapseSignerInteraction(interaction: string): CollapsedSignerInteraction {\n switch (interaction) {\n case 'confirm-open-app':\n return EConnectorInteraction.ConfirmOpenApp;\n case 'unlock-device':\n return EConnectorInteraction.UnlockDevice;\n case 'interaction-complete':\n return EConnectorInteraction.InteractionComplete;\n default:\n return EConnectorInteraction.ConfirmOnDevice;\n }\n}\n","import { HardwareErrorCode, stripHex } from '@onekeyfe/hwk-adapter-core';\nimport { Psbt } from 'bitcoinjs-lib';\n\nimport { collapseSignerInteraction, normalizePath } from './utils';\nimport { SignerBtc } from '../../signer/SignerBtc';\nimport { debugError, debugLog } from '../../utils/debugLog';\n\nimport type { ConnectorContext } from './types';\n\n// ---------------------------------------------------------------------------\n// Call param types\n// ---------------------------------------------------------------------------\n\nexport interface BtcGetAddressCallParams {\n /** Account-level derivation path (3 levels, e.g. \"m/86'/0'/0'\") */\n path: string;\n coin?: string;\n showOnDevice?: boolean;\n /** Address index within the account (default: 0) */\n addressIndex?: number;\n /** Whether this is a change address (default: false) */\n change?: boolean;\n}\n\nexport interface BtcGetPublicKeyCallParams {\n path: string;\n coin?: string;\n showOnDevice?: boolean;\n}\n\nexport interface BtcSignTransactionCallParams {\n psbt?: string;\n coin: string;\n /** Account-level derivation path for wallet template determination (e.g. \"84'/0'/0'\"). */\n path?: string;\n}\n\nexport interface BtcSignPsbtCallParams {\n psbt: string;\n coin?: string;\n path?: string;\n}\n\nexport interface BtcSignMessageCallParams {\n path: string;\n message: string;\n coin?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Internal -- BIP-44 purpose → Ledger wallet template\n// ---------------------------------------------------------------------------\n\n/**\n * BIP-44 purpose → Ledger descriptor template. Throws on unknown —\n * silent NATIVE_SEGWIT fallback would yield wrong addresses for\n * multisig (m/48') / legacy BIP-45 accounts. DDT is injected because\n * it comes from a runtime `importLedgerKit`.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction _purposeToTemplate(purpose: string | undefined, DDT: any): any {\n switch (purpose) {\n case '44':\n return DDT.LEGACY;\n case '49':\n return DDT.NESTED_SEGWIT;\n case '84':\n return DDT.NATIVE_SEGWIT;\n case '86':\n return DDT.TAPROOT;\n default:\n throw Object.assign(new Error(`Unsupported BTC purpose: m/${purpose ?? '<undefined>'}'`), {\n code: HardwareErrorCode.InvalidParams,\n });\n }\n}\n\n// ---------------------------------------------------------------------------\n// Handlers\n// ---------------------------------------------------------------------------\n\nexport async function btcGetAddress(\n ctx: ConnectorContext,\n sessionId: string,\n params: BtcGetAddressCallParams\n): Promise<{ address: string; path: string }> {\n const btcSigner = await _createBtcSigner(ctx, sessionId);\n const path = normalizePath(params.path);\n\n try {\n const { DefaultWallet, DefaultDescriptorTemplate } = await ctx.importLedgerKit(\n '@ledgerhq/device-signer-kit-bitcoin'\n );\n const purpose = path.split('/')[0]?.replace(/'/g, '');\n const template = _purposeToTemplate(purpose, DefaultDescriptorTemplate);\n const wallet = new DefaultWallet(path, template);\n\n debugLog('[LedgerConnector] btcGetAddress params:', {\n path,\n purpose,\n template,\n addressIndex: params.addressIndex,\n change: params.change,\n showOnDevice: params.showOnDevice,\n });\n\n const result = await btcSigner.getWalletAddress(wallet, params.addressIndex ?? 0, {\n checkOnDevice: params.showOnDevice ?? false,\n change: params.change ?? false,\n });\n return { address: result.address, path: params.path };\n } catch (err) {\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err);\n } finally {\n ctx.clearCanceller(sessionId);\n }\n}\n\nexport async function btcGetPublicKey(\n ctx: ConnectorContext,\n sessionId: string,\n params: BtcGetPublicKeyCallParams\n): Promise<{ xpub: string; path: string }> {\n const btcSigner = await _createBtcSigner(ctx, sessionId);\n const path = normalizePath(params.path);\n\n debugLog('[LedgerConnector] btcGetPublicKey called, path:', path, 'sessionId:', sessionId);\n try {\n const xpub = await btcSigner.getExtendedPublicKey(path, {\n checkOnDevice: params.showOnDevice ?? false,\n });\n debugLog('[LedgerConnector] btcGetPublicKey success, xpub:', `${xpub?.substring(0, 20)}...`);\n return { xpub, path: params.path };\n } catch (err) {\n debugError('[LedgerConnector] btcGetPublicKey error, path:', path, 'err:', err);\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err);\n } finally {\n ctx.clearCanceller(sessionId);\n }\n}\n\nexport async function btcSignTransaction(\n ctx: ConnectorContext,\n sessionId: string,\n params: BtcSignTransactionCallParams\n): Promise<{ serializedTx: string }> {\n if (!params.psbt) {\n throw Object.assign(\n new Error('Ledger requires PSBT format for BTC transaction signing. Provide params.psbt.'),\n { code: HardwareErrorCode.InvalidParams }\n );\n }\n\n const btcSigner = await _createBtcSigner(ctx, sessionId);\n\n try {\n const { DefaultWallet, DefaultDescriptorTemplate } = await ctx.importLedgerKit(\n '@ledgerhq/device-signer-kit-bitcoin'\n );\n\n // Determine wallet template from the account-level derivation path\n const path = normalizePath(params.path || \"84'/0'/0'\");\n const purpose = path.split('/')[0]?.replace(/'/g, '');\n const template = _purposeToTemplate(purpose, DefaultDescriptorTemplate);\n debugLog('[LedgerConnector] btcSignTransaction wallet:', { path, purpose, template });\n\n const wallet = new DefaultWallet(path, template);\n\n const signedTxHex = await btcSigner.signTransaction(wallet, params.psbt);\n\n return { serializedTx: stripHex(signedTxHex) };\n } catch (err) {\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err);\n } finally {\n ctx.clearCanceller(sessionId);\n }\n}\n\nexport async function btcSignPsbt(\n ctx: ConnectorContext,\n sessionId: string,\n params: BtcSignPsbtCallParams\n): Promise<{ signedPsbt: string }> {\n if (!params.psbt) {\n throw Object.assign(new Error('btcSignPsbt requires params.psbt'), {\n code: HardwareErrorCode.InvalidParams,\n });\n }\n\n const btcSigner = await _createBtcSigner(ctx, sessionId);\n\n try {\n const { DefaultWallet, DefaultDescriptorTemplate } = await ctx.importLedgerKit(\n '@ledgerhq/device-signer-kit-bitcoin'\n );\n\n const path = normalizePath(params.path || \"84'/0'/0'\");\n const purpose = path.split('/')[0]?.replace(/'/g, '');\n const template = _purposeToTemplate(purpose, DefaultDescriptorTemplate);\n debugLog('[LedgerConnector] btcSignPsbt wallet:', { path, purpose, template });\n\n const wallet = new DefaultWallet(path, template);\n\n const signatures = (await btcSigner.signPsbt(wallet, params.psbt)) as Array<{\n inputIndex: number;\n pubkey: Uint8Array;\n signature: Uint8Array;\n tapleafHash?: Uint8Array;\n }>;\n debugLog('[LedgerConnector] btcSignPsbt signatures received:', signatures.length);\n\n const signedPsbtHex = _applySignaturesToPsbt(params.psbt, signatures);\n return { signedPsbt: signedPsbtHex };\n } catch (err) {\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err);\n } finally {\n ctx.clearCanceller(sessionId);\n }\n}\n\nexport async function btcSignMessage(\n ctx: ConnectorContext,\n sessionId: string,\n params: BtcSignMessageCallParams\n): Promise<{ signature: string; address?: string }> {\n const btcSigner = await _createBtcSigner(ctx, sessionId);\n const path = normalizePath(params.path);\n\n try {\n // signMessage returns { r: HexaString, s: HexaString, v: number }\n const result = await btcSigner.signMessage(path, params.message);\n\n // BIP-137: signature = v(1) + r(32) + s(32); returned as hex (OneKey SDK style).\n const vHex = result.v.toString(16).padStart(2, '0');\n const rHex = stripHex(result.r).padStart(64, '0');\n const sHex = stripHex(result.s).padStart(64, '0');\n\n return { signature: `${vHex}${rHex}${sHex}` };\n } catch (err) {\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err);\n } finally {\n ctx.clearCanceller(sessionId);\n }\n}\n\nexport async function btcGetMasterFingerprint(\n ctx: ConnectorContext,\n sessionId: string,\n params?: { skipOpenApp?: boolean }\n): Promise<{ masterFingerprint: string }> {\n const btcSigner = await _createBtcSigner(ctx, sessionId);\n\n try {\n const fingerprint: Uint8Array = await btcSigner.getMasterFingerprint({\n skipOpenApp: params?.skipOpenApp,\n });\n // Convert Uint8Array to hex string\n const hex = Array.from(fingerprint)\n .map(b => b.toString(16).padStart(2, '0'))\n .join('');\n return { masterFingerprint: hex };\n } catch (err) {\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err);\n } finally {\n ctx.clearCanceller(sessionId);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Internal -- BTC signer creation\n// ---------------------------------------------------------------------------\n\nasync function _createBtcSigner(ctx: ConnectorContext, sessionId: string): Promise<SignerBtc> {\n const dmk = await ctx.getOrCreateDmk();\n const { SignerBtcBuilder } = await ctx.importLedgerKit('@ledgerhq/device-signer-kit-bitcoin');\n const sdkSigner = new SignerBtcBuilder({ dmk, sessionId }).build();\n const signer = new SignerBtc(sdkSigner);\n\n // Wire up interaction events (open-app, unlock, sign, etc.)\n // DMK-specific values (sign-transaction, sign-personal-message,\n // verify-address) collapse to ConfirmOnDevice via the helper.\n signer.onInteraction = (interaction: string) => {\n debugLog('[LedgerConnector] btc.onInteraction:', interaction);\n ctx.emit('ui-event', {\n type: collapseSignerInteraction(interaction),\n payload: { sessionId },\n });\n };\n\n signer.onRegisterCanceller = cancel => {\n ctx.registerCanceller(sessionId, cancel);\n };\n\n return signer;\n}\n\n// ---------------------------------------------------------------------------\n// Internal -- Apply partial signatures to PSBT\n// ---------------------------------------------------------------------------\n\ntype PsbtInput = Psbt['data']['inputs'][number];\n\nfunction _isTaprootInput(input: PsbtInput): boolean {\n if (\n input.tapInternalKey ||\n input.tapKeySig ||\n input.tapLeafScript ||\n input.tapMerkleRoot ||\n input.tapBip32Derivation ||\n input.tapScriptSig\n )\n return true;\n // P2TR scriptPubKey: OP_1 (0x51) + PUSH32 (0x20) + <32B x-only>\n const script = input.witnessUtxo?.script;\n return !!(script && script.length === 34 && script[0] === 0x51 && script[1] === 0x20);\n}\n\nfunction _isScriptPathInput(input: PsbtInput): boolean {\n return !!(input.tapLeafScript && input.tapLeafScript.length > 0);\n}\n\n/**\n * Dispatch DMK-returned signatures to the correct PSBT field using the\n * input's scriptPubKey as authoritative signal; throws on shape violations.\n */\nexport function _applySignaturesToPsbt(\n psbtHex: string,\n signatures: Array<{\n inputIndex: number;\n pubkey: Uint8Array;\n signature: Uint8Array;\n tapleafHash?: Uint8Array;\n }>\n): string {\n const psbt = Psbt.fromHex(psbtHex);\n for (const sig of signatures) {\n const input = psbt.data.inputs[sig.inputIndex];\n if (!input) {\n throw new Error(`_applySignaturesToPsbt: no PSBT input at index ${sig.inputIndex}`);\n }\n const taproot = _isTaprootInput(input);\n const scriptPath = taproot && _isScriptPathInput(input);\n const hasLeafHash = !!(sig.tapleafHash && sig.tapleafHash.length > 0);\n\n if (scriptPath) {\n if (sig.pubkey.length !== 32)\n throw new Error(\n `input ${sig.inputIndex}: taproot script-path pubkey must be 32B, got ${sig.pubkey.length}`\n );\n if (!hasLeafHash)\n throw new Error(\n `input ${sig.inputIndex}: taproot script-path signature missing tapleafHash`\n );\n psbt.updateInput(sig.inputIndex, {\n tapScriptSig: [\n { pubkey: sig.pubkey, leafHash: sig.tapleafHash!, signature: sig.signature },\n ],\n });\n } else if (taproot) {\n if (sig.pubkey.length !== 32)\n throw new Error(\n `input ${sig.inputIndex}: taproot key-path pubkey must be 32B, got ${sig.pubkey.length}`\n );\n if (hasLeafHash)\n throw new Error(\n `input ${sig.inputIndex}: taproot key-path signature must not carry tapleafHash`\n );\n psbt.updateInput(sig.inputIndex, { tapKeySig: sig.signature });\n } else {\n if (sig.pubkey.length !== 33 && sig.pubkey.length !== 65)\n throw new Error(\n `input ${sig.inputIndex}: ECDSA pubkey must be 33B or 65B, got ${sig.pubkey.length}`\n );\n if (hasLeafHash)\n throw new Error(`input ${sig.inputIndex}: ECDSA signature must not carry tapleafHash`);\n psbt.updateInput(sig.inputIndex, {\n partialSig: [{ pubkey: sig.pubkey, signature: sig.signature }],\n });\n }\n }\n return psbt.toHex();\n}\n","import { hexToBytes } from '@onekeyfe/hwk-adapter-core';\n\nimport { deviceActionToPromise } from './deviceActionToPromise';\nimport { debugError, debugLog } from '../utils/debugLog';\n\nimport type { CancelReason } from './deviceActionToPromise';\nimport type { SignerBtc as ISdkSignerBtc } from '@ledgerhq/device-signer-kit-bitcoin';\nimport type { SignerBtcAddress } from '../types';\n\n// Extract parameter types from the real SignerBtc interface to avoid deep path imports.\ntype BtcWallet = Parameters<ISdkSignerBtc['getWalletAddress']>[0];\ntype BtcPsbt = Parameters<ISdkSignerBtc['signPsbt']>[1];\ntype BtcPsbtOptions = Parameters<ISdkSignerBtc['signPsbt']>[2];\ntype BtcMessageOptions = Parameters<ISdkSignerBtc['signMessage']>[2];\n\n/** Decode hex string (with or without 0x prefix) to UTF-8 text. */\nfunction hexToUtf8(hex: string): string {\n return new TextDecoder().decode(hexToBytes(hex));\n}\n\n/** Timeout for user-interactive operations (sign, verify). */\nconst INTERACTIVE_TIMEOUT_MS = 5 * 60_000;\n\n/**\n * Wraps Ledger's BTC SDK signer (Observable-based DeviceActions) into\n * a simple async interface returning plain serializable data.\n */\nexport class SignerBtc {\n onInteraction?: (interaction: string) => void;\n\n onRegisterCanceller?: (cancel: (reason?: CancelReason) => void) => void;\n\n // eslint-disable-next-line no-useless-constructor, no-empty-function\n constructor(private readonly _sdk: ISdkSignerBtc) {}\n\n async getWalletAddress(\n wallet: BtcWallet,\n addressIndex: number,\n options?: { checkOnDevice?: boolean; change?: boolean }\n ): Promise<SignerBtcAddress> {\n const action = this._sdk.getWalletAddress(wallet, addressIndex, {\n checkOnDevice: options?.checkOnDevice ?? false,\n change: options?.change ?? false,\n });\n return deviceActionToPromise<SignerBtcAddress>(\n action,\n this.onInteraction,\n undefined,\n this.onRegisterCanceller\n );\n }\n\n async getExtendedPublicKey(\n derivationPath: string,\n options?: { checkOnDevice?: boolean }\n ): Promise<string> {\n debugLog(\n '[SignerBtc] getExtendedPublicKey called, path:',\n derivationPath,\n 'options:',\n JSON.stringify(options)\n );\n const action = this._sdk.getExtendedPublicKey(derivationPath, {\n checkOnDevice: options?.checkOnDevice ?? false,\n });\n try {\n // DMK returns { extendedPublicKey: string }, unwrap it\n const result = await deviceActionToPromise<string | { extendedPublicKey: string }>(\n action,\n this.onInteraction,\n undefined,\n this.onRegisterCanceller\n );\n debugLog(\n '[SignerBtc] getExtendedPublicKey result type:',\n typeof result,\n 'value:',\n typeof result === 'string'\n ? `${result.substring(0, 20)}...`\n : JSON.stringify(result).substring(0, 50)\n );\n if (typeof result === 'string') return result;\n return result.extendedPublicKey;\n } catch (err) {\n debugError('[SignerBtc] getExtendedPublicKey error:', err);\n throw err;\n }\n }\n\n async getMasterFingerprint(options?: { skipOpenApp?: boolean }): Promise<Uint8Array> {\n const action = this._sdk.getMasterFingerprint(options);\n const result = await deviceActionToPromise<{ masterFingerprint: Uint8Array }>(\n action,\n this.onInteraction,\n undefined,\n this.onRegisterCanceller\n );\n return result.masterFingerprint;\n }\n\n /**\n * Sign a PSBT and return the array of partial signatures.\n * The `wallet` param is a DefaultWallet or WalletPolicy instance.\n * The `psbt` param can be a hex string, base64 string, or Uint8Array.\n */\n async signPsbt(wallet: BtcWallet, psbt: BtcPsbt, options?: BtcPsbtOptions): Promise<unknown[]> {\n const action = this._sdk.signPsbt(wallet, psbt, options);\n return deviceActionToPromise<unknown[]>(\n action,\n this.onInteraction,\n INTERACTIVE_TIMEOUT_MS,\n this.onRegisterCanceller\n );\n }\n\n /**\n * Sign a PSBT and return the fully extracted raw transaction as a hex string.\n * Like signPsbt, but also finalises the PSBT and extracts the transaction.\n */\n async signTransaction(\n wallet: BtcWallet,\n psbt: BtcPsbt,\n options?: BtcPsbtOptions\n ): Promise<string> {\n const action = this._sdk.signTransaction(wallet, psbt, options);\n return deviceActionToPromise<string>(\n action,\n this.onInteraction,\n INTERACTIVE_TIMEOUT_MS,\n this.onRegisterCanceller\n );\n }\n\n /**\n * Sign a message with the BTC app (BIP-137 / \"Bitcoin Signed Message\").\n * Returns `{ r, s, v }` signature object.\n */\n async signMessage(\n derivationPath: string,\n message: string,\n options?: BtcMessageOptions\n ): Promise<{ r: string; s: string; v: number }> {\n // DMK uses TextEncoder to convert message string to bytes.\n // We receive hex-encoded message, so decode hex -> UTF-8 text first.\n const action = this._sdk.signMessage(derivationPath, hexToUtf8(message), options);\n return deviceActionToPromise<{ r: string; s: string; v: number }>(\n action,\n this.onInteraction,\n INTERACTIVE_TIMEOUT_MS,\n this.onRegisterCanceller\n );\n }\n}\n","import { bytesToHex, hexToBytes } from '@onekeyfe/hwk-adapter-core';\n\nimport { collapseSignerInteraction, normalizePath } from './utils';\nimport { SignerSol } from '../../signer/SignerSol';\nimport { debugLog } from '../../utils/debugLog';\n\nimport type { ConnectorContext } from './types';\n\n// ---------------------------------------------------------------------------\n// Call param types\n// ---------------------------------------------------------------------------\n\nexport interface SolGetAddressCallParams {\n path: string;\n showOnDevice?: boolean;\n}\n\nexport interface SolSignTransactionCallParams {\n path: string;\n /** Hex-encoded serialized transaction bytes (no 0x prefix) */\n serializedTx: string;\n}\n\nexport interface SolSignMessageCallParams {\n path: string;\n /** Message bytes as hex string (no 0x prefix) */\n message: string;\n}\n\n// ---------------------------------------------------------------------------\n// Handlers\n// ---------------------------------------------------------------------------\n\nexport async function solGetAddress(\n ctx: ConnectorContext,\n sessionId: string,\n params: SolGetAddressCallParams\n): Promise<{ address: string; path: string }> {\n const solSigner = await _createSolSigner(ctx, sessionId);\n const path = normalizePath(params.path);\n\n try {\n // Ledger Solana signer returns a base58-encoded Ed25519 public key (= Solana address)\n const publicKey = await solSigner.getAddress(path, {\n checkOnDevice: params.showOnDevice ?? false,\n });\n return { address: publicKey, path: params.path };\n } catch (err) {\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err);\n } finally {\n ctx.clearCanceller(sessionId);\n }\n}\n\nexport async function solSignTransaction(\n ctx: ConnectorContext,\n sessionId: string,\n params: SolSignTransactionCallParams\n): Promise<{ signature: string }> {\n const solSigner = await _createSolSigner(ctx, sessionId);\n const path = normalizePath(params.path);\n const txBytes = hexToBytes(params.serializedTx);\n\n try {\n const result = await solSigner.signTransaction(path, txBytes);\n return { signature: bytesToHex(result) };\n } catch (err) {\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err);\n } finally {\n ctx.clearCanceller(sessionId);\n }\n}\n\nexport async function solSignMessage(\n ctx: ConnectorContext,\n sessionId: string,\n params: SolSignMessageCallParams\n): Promise<{ signature: string }> {\n const solSigner = await _createSolSigner(ctx, sessionId);\n const path = normalizePath(params.path);\n const messageBytes = hexToBytes(params.message);\n\n try {\n // DMK signMessage returns { signature: string }, not raw Uint8Array\n const result = await solSigner.signMessage(path, messageBytes);\n return { signature: result.signature };\n } catch (err) {\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err);\n } finally {\n ctx.clearCanceller(sessionId);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Internal -- SOL signer creation\n// ---------------------------------------------------------------------------\n\nasync function _createSolSigner(ctx: ConnectorContext, sessionId: string): Promise<SignerSol> {\n const dmk = await ctx.getOrCreateDmk();\n const { ContextModuleBuilder } = await ctx.importLedgerKit('@ledgerhq/context-module');\n const { SignerSolanaBuilder } = await ctx.importLedgerKit('@ledgerhq/device-signer-kit-solana');\n const contextModule = new ContextModuleBuilder({}).removeDefaultLoaders().build();\n const sdkSigner = new SignerSolanaBuilder({ dmk, sessionId })\n .withContextModule(contextModule)\n .build();\n const signer = new SignerSol(sdkSigner);\n\n // Wire up interaction events (verify-address, sign, etc.)\n // DMK-specific values (verify-address, sign-transaction, sign-personal-message)\n // collapse to ConfirmOnDevice via the helper.\n signer.onInteraction = (interaction: string) => {\n debugLog('[LedgerConnector] sol.onInteraction:', interaction);\n ctx.emit('ui-event', {\n type: collapseSignerInteraction(interaction),\n payload: { sessionId },\n });\n };\n\n signer.onRegisterCanceller = cancel => {\n ctx.registerCanceller(sessionId, cancel);\n };\n\n return signer;\n}\n","import { deviceActionToPromise } from './deviceActionToPromise';\n\nimport type { CancelReason } from './deviceActionToPromise';\nimport type { SignerSolana as ISdkSignerSol } from '@ledgerhq/device-signer-kit-solana';\n\n// Extract parameter types from the real SignerSolana interface to avoid deep path imports.\ntype SolTxOptions = Parameters<ISdkSignerSol['signTransaction']>[2];\ntype SolMsgOptions = Parameters<ISdkSignerSol['signMessage']>[2];\n\n/**\n * Wraps Ledger's Solana SDK signer (Observable-based DeviceActions) into\n * a simple async interface returning plain serializable data.\n *\n * The Solana signer's `getAddress` returns a base58-encoded Ed25519 public key,\n * which is also the Solana address.\n */\nexport class SignerSol {\n onInteraction?: (interaction: string) => void;\n\n onRegisterCanceller?: (cancel: (reason?: CancelReason) => void) => void;\n\n // eslint-disable-next-line no-useless-constructor, no-empty-function\n constructor(private readonly _sdk: ISdkSignerSol) {}\n\n /**\n * Get the Solana address (base58-encoded Ed25519 public key) at the given derivation path.\n */\n async getAddress(derivationPath: string, options?: { checkOnDevice?: boolean }): Promise<string> {\n const action = this._sdk.getAddress(derivationPath, {\n checkOnDevice: options?.checkOnDevice ?? false,\n });\n return deviceActionToPromise<string>(\n action,\n this.onInteraction,\n undefined,\n this.onRegisterCanceller\n );\n }\n\n /**\n * Sign a Solana transaction.\n */\n async signTransaction(\n derivationPath: string,\n transaction: Uint8Array,\n options?: SolTxOptions\n ): Promise<Uint8Array> {\n const action = this._sdk.signTransaction(derivationPath, transaction, options);\n return deviceActionToPromise<Uint8Array>(\n action,\n this.onInteraction,\n undefined,\n this.onRegisterCanceller\n );\n }\n\n /**\n * Sign a message with the Solana app.\n * DMK returns { signature: string } for signMessage (unlike signTransaction which returns Uint8Array).\n */\n async signMessage(\n derivationPath: string,\n message: string | Uint8Array,\n options?: SolMsgOptions\n ): Promise<{ signature: string }> {\n const action = this._sdk.signMessage(derivationPath, message, options);\n return deviceActionToPromise<{ signature: string }>(\n action,\n this.onInteraction,\n undefined,\n this.onRegisterCanceller\n );\n }\n}\n","import { HardwareErrorCode } from '@onekeyfe/hwk-adapter-core';\nimport Trx from '@ledgerhq/hw-app-trx';\n\nimport { normalizePath } from './utils';\nimport { withLegacyChainCall } from './legacyChainCall';\nimport { DmkTransport } from '../../transport/DmkTransport';\n\nimport type { ConnectorContext } from './types';\n\n// ---------------------------------------------------------------------------\n// Call param types\n// ---------------------------------------------------------------------------\n\nexport interface TronGetAddressCallParams {\n path: string;\n showOnDevice?: boolean;\n}\n\nexport interface TronSignTransactionCallParams {\n path: string;\n /** Protobuf-encoded raw transaction hex (no 0x prefix) */\n rawTxHex: string;\n /**\n * TRC token metadata for Ledger clear-signing. Omit → TRC-20 transfers\n * fall back to blind-signing (user sees only raw bytes on-device).\n */\n tokenSignatures?: string[];\n}\n\nexport interface TronSignMessageCallParams {\n path: string;\n /** Message hex (no 0x prefix) */\n messageHex: string;\n}\n\n// ---------------------------------------------------------------------------\n// Handlers\n// ---------------------------------------------------------------------------\n\nexport async function tronGetAddress(\n ctx: ConnectorContext,\n sessionId: string,\n params: TronGetAddressCallParams\n): Promise<{ address: string; publicKey: string; path: string }> {\n const path = normalizePath(params.path);\n const showOnDevice = params.showOnDevice ?? false;\n\n return withLegacyChainCall(\n ctx,\n sessionId,\n {\n appName: 'Tron',\n // Only show \"confirm on device\" UI when the device is actually going\n // to display the address for the user to verify.\n needsConfirmation: showOnDevice,\n },\n async sid => {\n const trx = await _createTrx(ctx, sid);\n const result = await trx.getAddress(path, showOnDevice);\n return { address: result.address, publicKey: result.publicKey, path: params.path };\n }\n );\n}\n\nexport async function tronSignTransaction(\n ctx: ConnectorContext,\n sessionId: string,\n params: TronSignTransactionCallParams\n): Promise<{ signature: string }> {\n if (!params.rawTxHex) {\n throw Object.assign(\n new Error('TRON signing requires a protobuf-encoded raw transaction hex (rawTxHex).'),\n { code: HardwareErrorCode.InvalidParams }\n );\n }\n\n const path = normalizePath(params.path);\n\n return withLegacyChainCall(\n ctx,\n sessionId,\n { appName: 'Tron', needsConfirmation: true },\n async sid => {\n const trx = await _createTrx(ctx, sid);\n const signature = await trx.signTransaction(\n path,\n params.rawTxHex,\n params.tokenSignatures ?? []\n );\n return { signature };\n }\n );\n}\n\nexport async function tronSignMessage(\n ctx: ConnectorContext,\n sessionId: string,\n params: TronSignMessageCallParams\n): Promise<{ signature: string }> {\n const path = normalizePath(params.path);\n\n return withLegacyChainCall(\n ctx,\n sessionId,\n { appName: 'Tron', needsConfirmation: true },\n async sid => {\n const trx = await _createTrx(ctx, sid);\n const signature = await trx.signPersonalMessage(path, params.messageHex);\n return { signature };\n }\n );\n}\n\n// ---------------------------------------------------------------------------\n// Internal\n// ---------------------------------------------------------------------------\n\nasync function _createTrx(ctx: ConnectorContext, sessionId: string): Promise<Trx> {\n const dmk = await ctx.getOrCreateDmk();\n return new Trx(new DmkTransport(dmk, sessionId));\n}\n","import { EConnectorInteraction } from '@onekeyfe/hwk-adapter-core';\n\nimport { isWrongAppError } from '../../errors';\nimport { AppManager } from '../../app/AppManager';\nimport { debugLog } from '../../utils/debugLog';\n\nimport type { ConnectorContext } from './types';\n\nexport interface LegacyChainCallOptions {\n /** Target Ledger app name, e.g. 'Tron' / 'XRP' / 'Cardano'. */\n appName: string;\n /**\n * Whether the action triggers an on-device confirm prompt (sign, verify).\n * Controls the ConfirmOnDevice / InteractionComplete pair around `action`.\n * `false` for silent ops like getAddress(showOnDevice=false).\n */\n needsConfirmation: boolean;\n}\n\n/** `appName` reserved for future per-app extension. */\nexport function isLegacyWrongAppError(err: unknown, _appName: string): boolean {\n return isWrongAppError(err);\n}\n\n/**\n * Run a legacy-SDK device call (TRON et al. that lack `@ledgerhq/device-signer-kit-*`):\n * 1. ensureAppOpen pre-flight (legacy hw-app-* bypasses DMK DeviceAction).\n * 2. Emit ConfirmOnDevice when `needsConfirmation`.\n * 3. action().\n * 4. Always close any prompt with InteractionComplete (symmetric on success/failure).\n * 5. Retry once on wrong-app: re-ensure + clear signers + rerun action.\n */\nexport async function withLegacyChainCall<T>(\n ctx: ConnectorContext,\n sessionId: string,\n options: LegacyChainCallOptions,\n action: (sid: string) => Promise<T>\n): Promise<T> {\n const { appName, needsConfirmation } = options;\n\n // wrapError calls below pass `{ defaultAppName: appName }` explicitly even\n // though LedgerConnectorBase.dispatcher already injects it via _ctxForMethod.\n // Reason: this utility receives `appName` as an own parameter — it is the\n // source of truth for which app it's calling, so it must not silently rely\n // on whatever wrapError happens to be on the ctx passed in. If a future\n // caller invokes withLegacyChainCall outside the dispatcher, behavior stays\n // correct.\n\n // Tracks whether ensureAppOpen showed ConfirmOpenApp; if so the UI atom is\n // `openApp` and we owe a matching InteractionComplete.\n let openAppPromptShown = false;\n const onAppOpenPrompt = () => {\n openAppPromptShown = true;\n ctx.emit('ui-event', {\n type: EConnectorInteraction.ConfirmOpenApp,\n payload: { sessionId },\n });\n };\n\n // For bail-out paths that skip runOnce's finally (e.g. ensureAppOpen throws).\n const closeOpenAppUiIfShown = () => {\n if (openAppPromptShown) {\n ctx.emit('ui-event', {\n type: EConnectorInteraction.InteractionComplete,\n payload: { sessionId },\n });\n openAppPromptShown = false;\n }\n };\n\n // ① Pre-flight ensureAppOpen.\n try {\n await _ensureAppOpen(ctx, sessionId, appName, onAppOpenPrompt);\n } catch (err) {\n debugLog(\n '[LegacyChainCall] pre-flight ensureAppOpen failed:',\n appName,\n (err as Error)?.message\n );\n closeOpenAppUiIfShown();\n throw ctx.wrapError(err, { defaultAppName: appName });\n }\n\n const runOnce = async (): Promise<T> => {\n let confirmEmitted = false;\n if (needsConfirmation) {\n ctx.emit('ui-event', {\n type: EConnectorInteraction.ConfirmOnDevice,\n payload: { sessionId },\n });\n confirmEmitted = true;\n }\n\n try {\n return await action(sessionId);\n } finally {\n // Symmetry: any prompt we showed (ConfirmOpenApp or ConfirmOnDevice)\n // is closed here, on both success and failure. If neither was shown,\n // we don't fire a stray Complete (the UI atom was already undefined).\n if (confirmEmitted || openAppPromptShown) {\n ctx.emit('ui-event', {\n type: EConnectorInteraction.InteractionComplete,\n payload: { sessionId },\n });\n openAppPromptShown = false;\n }\n }\n };\n\n try {\n return await runOnce();\n } catch (err) {\n if (!isLegacyWrongAppError(err, appName)) {\n debugLog('[LegacyChainCall] non-wrong-app failure:', appName, (err as Error)?.message);\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err, { defaultAppName: appName });\n }\n\n // ② Wrong-app fallback: user may have switched app between ① and the\n // action, or some edge state slipped through. Re-ensure and retry once.\n debugLog('[LegacyChainCall] wrong-app detected, retrying:', appName);\n try {\n await _ensureAppOpen(ctx, sessionId, appName, onAppOpenPrompt);\n } catch (switchErr) {\n debugLog(\n '[LegacyChainCall] retry ensureAppOpen failed:',\n appName,\n (switchErr as Error)?.message\n );\n closeOpenAppUiIfShown();\n throw ctx.wrapError(switchErr, { defaultAppName: appName });\n }\n ctx.clearAllSigners();\n\n const result = await runOnce();\n debugLog('[LegacyChainCall] retry succeeded:', appName);\n return result;\n }\n}\n\nasync function _ensureAppOpen(\n ctx: ConnectorContext,\n sessionId: string,\n appName: string,\n onPrompt: () => void\n): Promise<void> {\n const dmk = await ctx.getOrCreateDmk();\n const appManager = new AppManager(dmk);\n await appManager.ensureAppOpen(sessionId, appName, onPrompt);\n}\n","import {\n CloseAppCommand,\n type DeviceManagementKit,\n GetAppAndVersionCommand,\n OpenAppCommand,\n isSuccessCommandResult,\n} from '@ledgerhq/device-management-kit';\nimport { HardwareErrorCode } from '@onekeyfe/hwk-adapter-core';\n\nimport { ERROR_TAG } from '../errors';\nimport { debugLog } from '../utils/debugLog';\n\n/**\n * Map of chain ticker symbols to the Ledger app name\n * that must be open to sign transactions for that chain.\n */\nexport const APP_NAME_MAP: Record<string, string> = {\n ETH: 'Ethereum',\n BTC: 'Bitcoin',\n SOL: 'Solana',\n TRX: 'Tron',\n XRP: 'XRP',\n ADA: 'Cardano',\n DOT: 'Polkadot',\n ATOM: 'Cosmos',\n};\n\n/** The name reported by the Ledger when it sits on the home screen. */\nconst DASHBOARD_APP_NAME = 'BOLOS';\n\ninterface AppManagerOptions {\n waitMs?: number;\n maxRetries?: number;\n}\n\n/**\n * Orchestrates opening / closing Ledger on-device apps so that the\n * correct signer application is running before any signing call.\n */\nexport class AppManager {\n private readonly _dmk: DeviceManagementKit;\n\n private readonly _waitMs: number;\n\n private readonly _maxRetries: number;\n\n constructor(dmk: DeviceManagementKit, options?: AppManagerOptions) {\n this._dmk = dmk;\n this._waitMs = options?.waitMs ?? 1000;\n this._maxRetries = options?.maxRetries ?? 10;\n }\n\n /**\n * Return the Ledger app name for a given chain ticker,\n * or undefined if the chain is not supported.\n */\n static getAppName(chain: string): string | undefined {\n return APP_NAME_MAP[chain];\n }\n\n /**\n * Ensure the target app is open on the device identified by `sessionId`.\n *\n * Flow:\n * 1. Check the currently running app.\n * 2. If it is already the target, return immediately.\n * 3. If a different app is running (not dashboard), close it first.\n * 4. Open the target app.\n * 5. Poll until the device confirms the target app is running.\n */\n /**\n * @param onConfirmOnDevice Called BEFORE OpenAppCommand is issued — the\n * device is about to display \"Open <app>\" on screen and wait for the\n * user's button press. UI consumers should show their \"open app\" prompt\n * in response. NOT called when the target app is already open (no user\n * interaction needed in that case).\n *\n * Important: OpenAppCommand is blocking. It does not resolve until the user\n * has physically confirmed on the device, so anything that runs AFTER\n * `await this._openApp(...)` lands AFTER the prompt is already gone.\n * Hence the callback must fire BEFORE that await.\n */\n async ensureAppOpen(\n sessionId: string,\n targetAppName: string,\n onConfirmOnDevice?: () => void\n ): Promise<void> {\n const currentApp = await this._getCurrentApp(sessionId);\n\n if (currentApp === targetAppName) {\n return;\n }\n\n // If we're not on the dashboard, close the current app first\n if (!this._isDashboard(currentApp)) {\n await this._closeCurrentApp(sessionId);\n // Wait for dashboard to become active\n await this._waitForApp(sessionId, DASHBOARD_APP_NAME);\n }\n\n // Notify UI BEFORE issuing the open-app APDU. OpenAppCommand blocks until\n // the user confirms on device, so by the time `_openApp` resolves the\n // prompt is already gone — the UI must be told ahead of the APDU.\n onConfirmOnDevice?.();\n\n // Open the target app — throws if not installed (0x6807).\n // Resolves only after the user has confirmed on the device screen.\n await this._openApp(sessionId, targetAppName);\n\n // Poll until the target app is confirmed open\n await this._waitForApp(sessionId, targetAppName);\n }\n\n // ---------------------------------------------------------------------------\n // Private helpers\n // ---------------------------------------------------------------------------\n\n private async _getCurrentApp(sessionId: string): Promise<string> {\n const result = await this._dmk.sendCommand({\n sessionId,\n command: new GetAppAndVersionCommand(),\n });\n if (isSuccessCommandResult(result)) {\n debugLog('[AppManager] currentApp:', result.data.name);\n return result.data.name;\n }\n // DMK returns errors as result.error rather than throwing — surface the\n // tag / errorCode / originalError so transport-level failures aren't\n // swallowed under a generic \"Failed to get current app\" string.\n const errResult = result as unknown as { error?: Record<string, unknown> };\n const dmkErr = errResult.error ?? {};\n const original = (dmkErr as { originalError?: unknown }).originalError;\n debugLog(\n '[AppManager] _getCurrentApp failed sessionId=',\n sessionId,\n 'tag=',\n (dmkErr as { _tag?: string })._tag,\n 'errorCode=',\n (dmkErr as { errorCode?: unknown }).errorCode,\n 'message=',\n (dmkErr as { message?: string }).message,\n 'originalErrorMessage=',\n (original as { message?: string })?.message ?? String(original ?? '')\n );\n throw Object.assign(\n new Error(\n (dmkErr as { message?: string }).message ?? 'Failed to get current app from device'\n ),\n {\n _tag: (dmkErr as { _tag?: string })._tag,\n errorCode: (dmkErr as { errorCode?: unknown }).errorCode,\n originalError: original,\n }\n );\n }\n\n private async _openApp(sessionId: string, appName: string): Promise<void> {\n const result = await this._dmk.sendCommand({\n sessionId,\n command: new OpenAppCommand({ appName }),\n });\n if (!isSuccessCommandResult(result)) {\n // DMK error CommandResults carry the APDU status in result.error.errorCode\n // (there is no top-level statusCode): 0x6807 = app not installed,\n // 0x5501 = user refused the \"Open app?\" prompt on device.\n const dmkErr = result.error;\n const errorCode =\n 'errorCode' in dmkErr && dmkErr.errorCode != null ? String(dmkErr.errorCode) : '';\n const message =\n 'message' in dmkErr && typeof dmkErr.message === 'string' ? dmkErr.message : '';\n debugLog(\n '[AppManager] openApp failed:',\n appName,\n 'errorCode:',\n errorCode,\n 'tag:',\n dmkErr._tag\n );\n let code: HardwareErrorCode | undefined;\n if (errorCode === '6807' || /unknown application/i.test(message)) {\n code = HardwareErrorCode.AppNotInstalled;\n } else if (errorCode === '5501' || dmkErr._tag === 'ActionRefusedError') {\n code = HardwareErrorCode.UserRejected;\n }\n throw Object.assign(new Error(`Failed to open \"${appName}\"`), {\n _tag: ERROR_TAG.OpenAppCommand,\n code,\n errorCode,\n statusCode: errorCode,\n appName,\n originalError: dmkErr,\n });\n }\n }\n\n private async _closeCurrentApp(sessionId: string): Promise<void> {\n debugLog('[AppManager] closeCurrentApp');\n await this._dmk.sendCommand({\n sessionId,\n command: new CloseAppCommand(),\n });\n }\n\n /**\n * Poll the device until the expected app is reported as running,\n * or throw after `_maxRetries` attempts.\n */\n private async _waitForApp(sessionId: string, expectedAppName: string): Promise<void> {\n let lastSeen = '';\n for (let i = 0; i < this._maxRetries; i++) {\n await this._wait();\n const current = await this._getCurrentApp(sessionId);\n lastSeen = current;\n if (current === expectedAppName) {\n return;\n }\n }\n debugLog(\n '[AppManager] waitForApp exhausted: expected=',\n expectedAppName,\n 'lastSeen=',\n lastSeen\n );\n throw new Error(\n `Ledger: failed to open \"${expectedAppName}\" after ${this._maxRetries} retries (last seen: ${lastSeen})`\n );\n }\n\n private _isDashboard(appName: string): boolean {\n return appName === DASHBOARD_APP_NAME;\n }\n\n private _wait(): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, this._waitMs));\n }\n}\n","import Transport from '@ledgerhq/hw-transport';\n\nimport type { DeviceManagementKit } from '@ledgerhq/device-management-kit';\n\n/**\n * Transport adapter that bridges Ledger's legacy hw-app-* SDKs to DMK's sendApdu.\n *\n * Legacy SDKs (hw-app-trx, hw-app-xrp, etc.) require a Transport instance.\n * This adapter wraps DMK's session-based sendApdu so legacy SDKs can run\n * over DMK's transport layer without a separate USB/HID connection.\n *\n * Usage:\n * const transport = new DmkTransport(dmk, sessionId);\n * const trx = new Trx(transport);\n * const address = await trx.getAddress(\"44'/195'/0'/0/0\");\n */\nexport class DmkTransport extends Transport {\n private _dmk: DeviceManagementKit;\n\n private _sessionId: string;\n\n constructor(dmk: DeviceManagementKit, sessionId: string) {\n super();\n this._dmk = dmk;\n this._sessionId = sessionId;\n }\n\n async exchange(apdu: Buffer): Promise<Buffer> {\n const response = await this._dmk.sendApdu({\n sessionId: this._sessionId,\n apdu: new Uint8Array(apdu),\n });\n\n // Legacy format: data + statusCode (2 bytes) concatenated\n const { data, statusCode } = response;\n const result = Buffer.alloc(data.length + 2);\n if (data.length > 0) {\n result.set(data, 0);\n }\n result.set(statusCode, data.length);\n return result;\n }\n\n async close(): Promise<void> {\n // DMK manages session lifecycle\n }\n}\n","/* eslint-disable max-classes-per-file -- both classes are duck-typed DMK DeviceAction implementations sharing the same internal types (OsVersionDeps / InternalApiLike / AnyState); splitting would push those types into a third file with no payoff. */\n/**\n * Duck-typed DMK DeviceAction implementations for the two flows DMK has no\n * typed wrapper for: fetching OS version and listing available apps in the\n * catalog. Both are routed through `executeDeviceAction` so the\n * `unlock-device` interaction surfaces through the same onInteraction\n * pipeline as every other call.\n */\nimport { DeviceActionStatus } from '@ledgerhq/device-management-kit';\nimport { Subject } from 'rxjs';\n\nimport type { GetOsVersionResponse } from '@ledgerhq/device-management-kit';\nimport type { Observable } from 'rxjs';\n\nexport interface DmkApplication {\n versionName: string;\n versionId: number;\n version: string;\n versionDisplayName: string | null;\n description: string | null;\n icon: string | null;\n bytes: number | null;\n currencyId: string | null;\n isDevTools: boolean;\n}\n\nexport type OsVersionDeps = {\n GetOsVersionCommand: new () => unknown;\n isSuccessCommandResult: (result: unknown) => result is { data: GetOsVersionResponse };\n};\n\ninterface InternalApiLike {\n sendCommand: (command: unknown) => Promise<unknown>;\n getManagerApiService: () => {\n getAppList: (deviceInfo: GetOsVersionResponse) => {\n run: () => Promise<{ isLeft: () => boolean; extract: () => unknown }>;\n };\n };\n}\n\ntype AnyState<T> =\n | { readonly status: DeviceActionStatus.NotStarted }\n | { readonly status: DeviceActionStatus.Pending; readonly intermediateValue: unknown }\n | { readonly status: DeviceActionStatus.Stopped }\n | { readonly status: DeviceActionStatus.Completed; readonly output: T }\n | { readonly status: DeviceActionStatus.Error; readonly error: unknown };\n\n// Wrapped as a DeviceAction (not raw sendCommand) so unlock-device interaction\n// flows through onInteraction like every other method.\nexport class GetOsVersionDeviceAction {\n readonly input = undefined;\n\n // eslint-disable-next-line no-useless-constructor, no-empty-function\n constructor(private readonly _deps: OsVersionDeps) {}\n\n _execute(internalApi: { sendCommand: (cmd: unknown) => Promise<unknown> }): {\n observable: Observable<AnyState<GetOsVersionResponse>>;\n cancel: () => void;\n } {\n const subject = new Subject<AnyState<GetOsVersionResponse>>();\n let cancelled = false;\n\n (async () => {\n try {\n subject.next({\n status: DeviceActionStatus.Pending,\n intermediateValue: { requiredUserInteraction: 'none' },\n });\n const result = await internalApi.sendCommand(new this._deps.GetOsVersionCommand());\n if (cancelled) return;\n if (!this._deps.isSuccessCommandResult(result)) {\n const errObj = (result as { error?: { message?: string } })?.error;\n throw new Error(errObj?.message ?? 'GetOsVersionCommand failed');\n }\n subject.next({ status: DeviceActionStatus.Completed, output: result.data });\n subject.complete();\n } catch (err) {\n if (cancelled) return;\n subject.next({ status: DeviceActionStatus.Error, error: err });\n subject.complete();\n }\n })();\n\n return {\n observable: subject.asObservable(),\n cancel: () => {\n cancelled = true;\n subject.next({ status: DeviceActionStatus.Stopped });\n subject.complete();\n },\n };\n }\n}\n\nexport class ListAvailableAppsDeviceAction {\n readonly input = undefined;\n\n private readonly _GetOsVersionCommand: new () => unknown;\n\n private readonly _isSuccessCommandResult: (\n result: unknown\n ) => result is { data: GetOsVersionResponse };\n\n constructor(deps: OsVersionDeps) {\n this._GetOsVersionCommand = deps.GetOsVersionCommand;\n this._isSuccessCommandResult = deps.isSuccessCommandResult;\n }\n\n _execute(internalApi: InternalApiLike): {\n observable: Observable<AnyState<DmkApplication[]>>;\n cancel: () => void;\n } {\n const subject = new Subject<AnyState<DmkApplication[]>>();\n let cancelled = false;\n\n (async () => {\n try {\n subject.next({\n status: DeviceActionStatus.Pending,\n intermediateValue: { requiredUserInteraction: 'none' },\n });\n\n const osVersionResult = await internalApi.sendCommand(new this._GetOsVersionCommand());\n if (cancelled) return;\n if (!this._isSuccessCommandResult(osVersionResult)) {\n const errObj = (osVersionResult as { error?: { message?: string } })?.error;\n throw new Error(errObj?.message ?? 'GetOsVersionCommand failed');\n }\n\n const managerApi = internalApi.getManagerApiService();\n const either = await managerApi.getAppList(osVersionResult.data).run();\n if (cancelled) return;\n if (either.isLeft()) {\n const httpErr = either.extract() as { message?: string };\n throw new Error(httpErr?.message ?? 'Manager API getAppList failed');\n }\n\n const apps = either.extract() as DmkApplication[];\n subject.next({ status: DeviceActionStatus.Completed, output: apps });\n subject.complete();\n } catch (err) {\n if (cancelled) return;\n subject.next({ status: DeviceActionStatus.Error, error: err });\n subject.complete();\n }\n })();\n\n return {\n observable: subject.asObservable(),\n cancel: () => {\n cancelled = true;\n subject.next({ status: DeviceActionStatus.Stopped });\n subject.complete();\n },\n };\n }\n}\n","/** Raised by DeviceApps.install when DMK reports the requested app is not in the catalog. */\nexport class AppNotFoundInCatalogError extends Error {\n readonly missingApplications: string[];\n\n constructor(missing: string[]) {\n super(`Ledger app not found in catalog: ${missing.join(', ')}`);\n this.name = 'AppNotFoundInCatalogError';\n this.missingApplications = missing;\n }\n}\n","import { deviceActionToPromise } from '../signer/deviceActionToPromise';\nimport { debugLog } from '../utils/debugLog';\nimport { GetOsVersionDeviceAction, ListAvailableAppsDeviceAction } from './customActions';\nimport { AppNotFoundInCatalogError } from './errors';\n\nimport type { DmkApplication } from './customActions';\nimport type { DeviceManagementKit, GetOsVersionResponse } from '@ledgerhq/device-management-kit';\nimport type { CancelReason } from '../signer/deviceActionToPromise';\n\nconst INSTALL_TIMEOUT_MS = 5 * 60_000;\n\nexport interface AppMetadata {\n versionName: string;\n versionId: number;\n version: string;\n versionDisplayName: string | null;\n description: string | null;\n icon: string | null;\n bytes: number | null;\n currencyId: string | null;\n isDevTools: boolean;\n}\n\n/**\n * Progress fraction reported by DMK's InstallOrUpdateAppsDeviceAction.\n * Note: DMK's raw `requiredUserInteraction` for install (e.g. allow-secure-connection,\n * allow-manager) is intentionally NOT exposed here — those signals are routed through\n * the public 'ui-event' channel (collapsed to EConnectorInteraction) and additionally\n * captured via debugLog in the connector for diagnosis.\n */\nexport interface InstallProgress {\n progress: number;\n}\n\nexport type InstallProgressCallback = (progress: InstallProgress) => void;\n\nexport interface InstallAppCallParams {\n appName: string;\n}\n\nexport interface ListInstalledAppsCallParams {\n unlockTimeout?: number;\n}\n\nexport interface FirmwareVersion {\n /** BOLOS version on the secure element — the user-facing firmware version. */\n seVersion: string;\n /** MCU SEPH (SE–MCU link protocol) version. */\n mcuSephVersion: string;\n /** MCU bootloader version. */\n mcuBootloaderVersion: string;\n /** Hardware revision (e.g. \"00\" / \"01\" on Nano X). */\n hwVersion: string;\n}\n\n/** Full GetOsVersionResponse projected to a plain serializable shape. */\nexport interface LedgerDeviceInfo extends FirmwareVersion {\n isBootloader: boolean;\n isOsu: boolean;\n targetId: number;\n seTargetId?: number;\n mcuTargetId?: number;\n /** Secure element flags as hex string (raw bytes turned readable). */\n seFlagsHex: string;\n}\n\n/**\n * OS-level device management (install, list apps). Mirrors SignerEth:\n * built fresh per call, consumer sets onInteraction / onRegisterCanceller.\n */\nexport class DeviceApps {\n onInteraction?: (interaction: string) => void;\n\n onRegisterCanceller?: (cancel: (reason?: CancelReason) => void) => void;\n\n /* eslint-disable no-useless-constructor, no-empty-function -- TS parameter properties pattern */\n constructor(\n private readonly _dmk: DeviceManagementKit,\n private readonly _sessionId: string,\n private readonly _ledgerKit: LedgerKitModule\n ) {}\n /* eslint-enable no-useless-constructor, no-empty-function */\n\n async listInstalled(options?: { unlockTimeout?: number }): Promise<AppMetadata[]> {\n const action = (this._dmk as unknown as DmkExecuteCapable).executeDeviceAction({\n sessionId: this._sessionId,\n deviceAction: new this._ledgerKit.ListAppsWithMetadataDeviceAction({\n input: { unlockTimeout: options?.unlockTimeout },\n }),\n });\n const result = await deviceActionToPromise<Array<DmkApplication | null>>(\n action,\n this.onInteraction,\n undefined,\n this.onRegisterCanceller\n );\n return result.filter((a): a is DmkApplication => a !== null).map(applicationToMetadata);\n }\n\n /** Installed app names via ListApps APDU. Offline (no manager-api), but still requires unlock + dashboard. */\n async listInstalledNames(options?: { unlockTimeout?: number }): Promise<string[]> {\n const action = (this._dmk as unknown as DmkExecuteCapable).executeDeviceAction({\n sessionId: this._sessionId,\n deviceAction: new this._ledgerKit.ListAppsDeviceAction({\n input: { unlockTimeout: options?.unlockTimeout },\n }),\n });\n const result = await deviceActionToPromise<Array<{ appName?: string } | null>>(\n action,\n this.onInteraction,\n undefined,\n this.onRegisterCanceller\n );\n return result\n .map(entry => entry?.appName)\n .filter((name): name is string => typeof name === 'string' && name.length > 0);\n }\n\n // Catalog lookup via custom device action — DMK has no typed wrapper for this.\n async listAvailable(): Promise<AppMetadata[]> {\n const customAction = new ListAvailableAppsDeviceAction({\n GetOsVersionCommand: this._ledgerKit.GetOsVersionCommand,\n isSuccessCommandResult: this._ledgerKit.isSuccessCommandResult,\n });\n const action = (this._dmk as unknown as DmkExecuteCapable).executeDeviceAction({\n sessionId: this._sessionId,\n deviceAction: customAction,\n });\n const result = await deviceActionToPromise<DmkApplication[]>(\n action,\n this.onInteraction,\n undefined,\n this.onRegisterCanceller\n );\n return result.map(applicationToMetadata);\n }\n\n async getFirmwareVersion(): Promise<FirmwareVersion> {\n const v = await this._fetchOsVersion();\n return {\n seVersion: v.seVersion,\n mcuSephVersion: v.mcuSephVersion,\n mcuBootloaderVersion: v.mcuBootloaderVersion,\n hwVersion: v.hwVersion,\n };\n }\n\n async getDeviceInfo(): Promise<LedgerDeviceInfo> {\n const v = await this._fetchOsVersion();\n return {\n isBootloader: v.isBootloader,\n isOsu: v.isOsu,\n targetId: v.targetId,\n seTargetId: v.seTargetId,\n mcuTargetId: v.mcuTargetId,\n seVersion: v.seVersion,\n seFlagsHex: bytesToHex(v.seFlags),\n mcuSephVersion: v.mcuSephVersion,\n mcuBootloaderVersion: v.mcuBootloaderVersion,\n hwVersion: v.hwVersion,\n };\n }\n\n // Sole sendCommand path — routed via executeDeviceAction so unlock-device\n // interaction flows through onInteraction like the other methods.\n private async _fetchOsVersion(): Promise<GetOsVersionResponse> {\n const customAction = new GetOsVersionDeviceAction({\n GetOsVersionCommand: this._ledgerKit.GetOsVersionCommand,\n isSuccessCommandResult: this._ledgerKit.isSuccessCommandResult,\n });\n const action = (this._dmk as unknown as DmkExecuteCapable).executeDeviceAction({\n sessionId: this._sessionId,\n deviceAction: customAction,\n });\n return deviceActionToPromise<GetOsVersionResponse>(\n action,\n this.onInteraction,\n undefined,\n this.onRegisterCanceller\n );\n }\n\n async install(\n appName: string,\n onProgress?: InstallProgressCallback,\n options?: { unlockTimeout?: number }\n ): Promise<void> {\n if (!appName) throw new Error('DeviceApps.install: appName is required');\n debugLog('[DeviceApps] install:', appName);\n\n // InstallOrUpdateAppsDeviceAction reads device metadata with a hardcoded\n // forceUpdate:false, so a warm session reuses the cached app list - stale\n // after apps were installed/uninstalled outside this flow. Force-refresh\n // first; the install action then reads the fresh cache.\n const refreshAction = (this._dmk as unknown as DmkExecuteCapable).executeDeviceAction({\n sessionId: this._sessionId,\n deviceAction: new this._ledgerKit.GetDeviceMetadataDeviceAction({\n input: {\n useSecureChannel: true,\n forceUpdate: true,\n unlockTimeout: options?.unlockTimeout,\n },\n }),\n });\n await deviceActionToPromise(\n refreshAction,\n this.onInteraction,\n INSTALL_TIMEOUT_MS,\n this.onRegisterCanceller\n );\n\n // Use InstallOrUpdateAppsDeviceAction (not InstallAppDeviceAction): it runs\n // UPDATE_DEVICE_METADATA → BUILD_INSTALL_PLAN → CHECK_IF_ENOUGH_MEMORY →\n // INSTALL_APPLICATION, so OOM fails fast (zero bytes written) and the refreshed\n // metadata feeds PredictOutOfMemoryTask accurate sizes — no client-side estimate.\n const action = (this._dmk as unknown as DmkExecuteCapable).executeDeviceAction({\n sessionId: this._sessionId,\n deviceAction: new this._ledgerKit.InstallOrUpdateAppsDeviceAction({\n input: {\n applications: [{ name: appName }],\n allowMissingApplication: false,\n unlockTimeout: options?.unlockTimeout,\n },\n }),\n });\n\n const result = await deviceActionToPromise<InstallOrUpdateAppsOutput>(\n action,\n this.onInteraction,\n INSTALL_TIMEOUT_MS,\n this.onRegisterCanceller,\n intermediateValue => {\n const iv = intermediateValue as\n | {\n requiredUserInteraction?: string;\n installPlan?: { currentProgress?: number } | null;\n }\n | undefined;\n // Surface DMK's install-specific interaction string (e.g. allow-secure-connection,\n // allow-manager, verify-app) into the debug log for post-hoc diagnosis. The\n // public 'ui-event' channel still emits the collapsed EConnectorInteraction so\n // existing UI consumers keep working.\n if (iv?.requiredUserInteraction && iv.requiredUserInteraction !== 'none') {\n debugLog('[DeviceApps] install interaction:', iv.requiredUserInteraction);\n }\n const progress = iv?.installPlan?.currentProgress;\n if (onProgress && typeof progress === 'number') {\n onProgress({ progress });\n }\n }\n );\n\n // DMK can resolve Completed with `missingApplications` populated when the\n // requested name is not in the catalog. allowMissingApplication=false should\n // make DMK reject, but we double-check on this side so the adapter never\n // returns success(undefined) for an install that didn't actually install.\n if (result?.missingApplications?.length > 0) {\n throw new AppNotFoundInCatalogError(result.missingApplications);\n }\n }\n}\n\nfunction bytesToHex(bytes: Uint8Array | undefined): string {\n if (!bytes) return '';\n return Array.from(bytes, b => b.toString(16).padStart(2, '0')).join('');\n}\n\nfunction applicationToMetadata(app: DmkApplication): AppMetadata {\n return {\n versionName: app.versionName,\n versionId: app.versionId,\n version: app.version,\n versionDisplayName: app.versionDisplayName,\n description: app.description,\n icon: app.icon,\n bytes: app.bytes,\n currencyId: app.currencyId,\n isDevTools: app.isDevTools,\n };\n}\n\n// Loosened DMK surface (we receive the module via dynamic importLedgerKit).\nexport interface LedgerKitModule {\n ListAppsWithMetadataDeviceAction: new (args: { input: unknown }) => unknown;\n ListAppsDeviceAction: new (args: { input: unknown }) => unknown;\n InstallOrUpdateAppsDeviceAction: new (args: { input: unknown }) => unknown;\n GetDeviceMetadataDeviceAction: new (args: { input: unknown }) => unknown;\n GetOsVersionCommand: new () => unknown;\n isSuccessCommandResult: (result: unknown) => result is { data: GetOsVersionResponse };\n}\n\ninterface InstallOrUpdateAppsOutput {\n successfullyInstalled: unknown[];\n alreadyInstalled: string[];\n missingApplications: string[];\n}\n\ninterface DmkExecuteCapable {\n // Loose return: deviceActionToPromise narrows the observable shape per-call.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n executeDeviceAction(args: { sessionId: string; deviceAction: unknown }): any;\n}\n","import { DeviceApps } from './DeviceApps';\n\nimport type { LedgerKitModule } from './DeviceApps';\nimport type { DeviceManagementKit } from '@ledgerhq/device-management-kit';\n\n/** Per-call DeviceApps factory (mirrors SignerManager); DMK actions hold per-action state. */\nexport class DeviceAppsManager {\n private readonly _dmk: DeviceManagementKit;\n\n private readonly _importLedgerKit: (pkg: string) => Promise<unknown>;\n\n constructor(dmk: DeviceManagementKit, importLedgerKit: (pkg: string) => Promise<unknown>) {\n this._dmk = dmk;\n this._importLedgerKit = importLedgerKit;\n }\n\n async getOrCreate(sessionId: string): Promise<DeviceApps> {\n const ledgerKit = (await this._importLedgerKit(\n '@ledgerhq/device-management-kit'\n )) as LedgerKitModule;\n return new DeviceApps(this._dmk, sessionId, ledgerKit);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars, class-methods-use-this\n invalidate(_sessionId: string): void {}\n\n // eslint-disable-next-line class-methods-use-this\n clearAll(): void {}\n}\n"],"mappings":"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A,IAC5B,SAAS,KAAK;AACZ,aAAO,KAAK,eAAe,GAAG;AAAA,IAChC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMA,cACE,WACA,UACA,QACA,cACA;AACA,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,mBACE,WACA,UACA,QACA,cACA;AACA,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,eACE,WACA,UACA,QACA,cACA;AACA,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,iBACE,WACA,UACA,QACA,cACA;AACA,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMA,cACE,WACA,UACA,QACA,cACA;AACA,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,gBACE,WACA,UACA,QACA,cACA;AACA,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,mBACE,WACA,UACA,QACA,cACA;AACA,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,YACE,WACA,UACA,QACA,cACA;AACA,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,eACE,WACA,UACA,QACA,cACA;AACA,WAAO,KAAK;AAAA,MACV;AA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","names":["import_hwk_adapter_core","import_hwk_adapter_core","result","import_hwk_adapter_core","import_hwk_adapter_core","import_hwk_adapter_core","import_hwk_adapter_core","import_hwk_adapter_core","import_hwk_adapter_core","INTERACTIVE_TIMEOUT_MS","import_hwk_adapter_core","ContextModuleBuilder","import_hwk_adapter_core","import_hwk_adapter_core","import_device_management_kit","import_hwk_adapter_core","Transport","Trx","import_device_management_kit","bytesToHex"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/adapter/LedgerAdapter.ts","../src/errors.ts","../src/utils/ledgerDmkTransport.ts","../src/utils/sdkEventBus.ts","../src/utils/debugLog.ts","../src/connector/LedgerConnectorBase.ts","../src/device/LedgerDeviceManager.ts","../src/signer/SignerManager.ts","../src/signer/SignerEth.ts","../src/signer/deviceActionToPromise.ts","../src/connector/chains/evm.ts","../src/connector/chains/utils.ts","../src/connector/chains/btc.ts","../src/signer/SignerBtc.ts","../src/connector/chains/sol.ts","../src/signer/SignerSol.ts","../src/connector/chains/tron.ts","../src/connector/chains/legacyChainCall.ts","../src/app/AppManager.ts","../src/transport/DmkTransport.ts","../src/device-apps/customActions.ts","../src/device-apps/errors.ts","../src/device-apps/DeviceApps.ts","../src/device-apps/DeviceAppsManager.ts"],"sourcesContent":["// Adapter\nexport { LedgerAdapter } from './adapter/LedgerAdapter';\n\n// Connector base class (used by connector packages)\nexport { LedgerConnectorBase } from './connector/LedgerConnectorBase';\nexport type { TransportFactory, LedgerConnectorBaseOptions } from './connector/LedgerConnectorBase';\n\n// Device management (used by connectors)\nexport { LedgerDeviceManager } from './device/LedgerDeviceManager';\n\n// Signer (used by connectors)\nexport { SignerManager } from './signer/SignerManager';\nexport { SignerEth } from './signer/SignerEth';\nexport { SignerBtc } from './signer/SignerBtc';\nexport { SignerSol } from './signer/SignerSol';\nexport { DmkTransport } from './transport/DmkTransport';\nexport { deviceActionToPromise } from './signer/deviceActionToPromise';\n\n// App management\nexport { AppManager } from './app/AppManager';\n\n// Types\nexport type {\n DmkDiscoveredDevice,\n DeviceActionState,\n SignerEvmAddress,\n SignerEvmSignature,\n SignerBtcAddress,\n} from './types';\n\n// Errors\nexport { isDeviceLockedError, ledgerFailure, mapLedgerError } from './errors';\nexport type { LedgerFailure } from './errors';\n\n// SDK-global event bus (logs today; extensible for firmware progress / etc.)\nexport { onSdkEvent, offSdkEvent } from './utils/sdkEventBus';\nexport type { SdkEvent, SdkEventListener, SdkLogEvent } from './utils/sdkEventBus';\n\n// BLE utilities (shared by connector packages)\nexport { debugLog } from './utils/debugLog';\nexport {\n isLedgerBleConnectionType,\n isLedgerBleDescriptor,\n isLedgerDmkBleTransport,\n} from './utils/ledgerDmkTransport';\n","import {\n CHAIN_FINGERPRINT_PATHS,\n DEVICE,\n DeviceJobQueue,\n EConnectorInteraction,\n HardwareErrorCode,\n TypedEventEmitter,\n UI_REQUEST,\n UI_REQUEST_PREEMPTED_TAG,\n UiRequestRegistry,\n deriveDeviceFingerprint,\n failure,\n rehydrateConnectorError,\n success,\n} from '@onekeyfe/hwk-adapter-core';\n\nimport {\n ERROR_TAG,\n createMultipleUsbLedgerDevicesError,\n isAppNotInstalledError,\n isConnectionLevelError,\n isDeviceDisconnectedError,\n isDeviceLockedError,\n isDeviceNotAdvertisingError,\n isStuckAppStateError,\n isTimeoutError,\n ledgerFailure,\n mapLedgerError,\n} from '../errors';\nimport { isLedgerBleConnectionType } from '../utils/ledgerDmkTransport';\nimport { debugError, debugLog } from '../utils/debugLog';\n\nimport type { AppMetadata, FirmwareVersion, LedgerDeviceInfo } from '../device-apps/DeviceApps';\nimport type {\n BtcAddress,\n BtcGetAddressParams,\n BtcGetPublicKeyParams,\n BtcPublicKey,\n BtcSignMsgParams,\n BtcSignPsbtParams,\n BtcSignTxParams,\n BtcSignature,\n BtcSignedPsbt,\n BtcSignedTx,\n ChainCapability,\n ChainForFingerprint,\n ConnectorCallResult,\n ConnectorDevice,\n ConnectorUiEvent,\n DeviceEventListener,\n DeviceInfo,\n DevicePermissionResponse,\n EvmAddress,\n EvmGetAddressParams,\n EvmSignMsgParams,\n EvmSignTxParams,\n EvmSignTypedDataParams,\n EvmSignature,\n EvmSignedTx,\n HardwareEvent,\n HardwareEventMap,\n ICommonCallParams,\n IConnector,\n IHardwareWallet,\n Response,\n SearchDevicesOptions,\n SolAddress,\n SolGetAddressParams,\n SolSignMsgParams,\n SolSignTxParams,\n SolSignature,\n SolSignedTx,\n TransportType,\n TronAddress,\n TronGetAddressParams,\n TronSignMsgParams,\n TronSignTxParams,\n TronSignature,\n TronSignedTx,\n UiResponseEvent,\n} from '@onekeyfe/hwk-adapter-core';\n\n/**\n * Result of `_verifyDeviceFingerprint`.\n *\n * On mismatch carries both the stored (expected) fingerprint and the\n * live (actual) one derived from the physically connected device.\n * Callers turn this into a `DeviceMismatch` failure via `formatDeviceMismatchError`.\n */\ntype IFingerprintVerifyResult =\n | { success: true }\n | { success: false; expected: string; actual: string };\n\ntype ConnectorCallFingerprint = {\n chain: ChainForFingerprint;\n deviceId: string;\n skipFingerprint: boolean;\n};\n\n// Fingerprints are deterministic 16-char hashes of fixed testnet paths,\n// not secrets — safe to log.\nfunction formatDeviceMismatchError(expected: string, actual: string): string {\n return `Wrong device: expected ${expected}, got ${actual}`;\n}\n\n/**\n * Ledger Bitcoin App constant `MAX_BIP44_ACCOUNT_RECOMMENDED`. Account index >=\n * this triggers `SW_NOT_SUPPORTED (0x6a82)` unless the call sets\n * `display=true`. See app-bitcoin-new src/handler/get_extended_pubkey.c.\n */\nconst BTC_HIGH_INDEX_THRESHOLD = 100;\n\nfunction btcAccountIndexFromPath(path: string): number | null {\n const segments = path.replace(/^m\\//, '').split('/');\n if (segments.length < 3) return null;\n const accountSeg = segments[2].replace(/['h]$/i, '');\n const accountIndex = parseInt(accountSeg, 10);\n return Number.isFinite(accountIndex) ? accountIndex : null;\n}\n\nexport class LedgerAdapter implements IHardwareWallet {\n readonly vendor = 'ledger' as const;\n\n private readonly connector: IConnector;\n\n private readonly emitter = new TypedEventEmitter<HardwareEventMap>();\n\n private _discoveredDevices = new Map<string, DeviceInfo>();\n\n private _sessions = new Map<string, string>();\n\n private readonly _uiRegistry = new UiRequestRegistry();\n\n // BTC App rejects account index >= 100 unless display=true. Cached per\n // adapter instance: first 100+ path asks the user once via UI request,\n // subsequent 100+ paths in the same session auto-promote silently.\n // The Ledger device itself still requires a per-call confirmation — that's\n // the Ledger app's safety boundary, not ours to bypass.\n private _btcHighIndexConfirmedThisSession = false;\n\n // Pure FIFO queue. New jobs chain onto the tail and run in order. The\n // queue is intentionally passive: it does not arbitrate, does not ask\n // the user. Callers wanting \"interrupt current?\" semantics must do so\n // explicitly via `getActiveJob()` + `forceCancelActive()` from the UI\n // layer. USB transports can't read multiple devices in parallel, and\n // BLE-only parallelism isn't worth the coordination cost.\n private readonly _jobQueue: DeviceJobQueue;\n\n // Shared across concurrent callers — only `cancel()` aborts.\n private _doConnectAbortController: AbortController | null = null;\n\n // Default for commonParams.autoInstallApp when a call doesn't specify it,\n // so the host can opt the whole adapter in once instead of per call.\n private readonly _defaultAutoInstallApp: boolean;\n\n constructor(connector: IConnector, options?: { autoInstallApp?: boolean }) {\n this.connector = connector;\n this._defaultAutoInstallApp = options?.autoInstallApp ?? false;\n this._jobQueue = new DeviceJobQueue();\n this.registerEventListeners();\n }\n\n // Transport\n get activeTransport(): TransportType | null {\n return isLedgerBleConnectionType(this.connector.connectionType) ? 'ble' : 'hid';\n }\n\n getAvailableTransports(): TransportType[] {\n return this.activeTransport ? [this.activeTransport] : [];\n }\n\n // Connector is bound at construction; switching requires a new adapter.\n switchTransport(_type: TransportType): Promise<void> {\n return Promise.resolve();\n }\n\n // Lifecycle\n init(_config?: unknown): Promise<void> {\n return Promise.resolve();\n }\n\n /**\n * Clear cached device/session state without tearing down the adapter.\n * Call before retrying after errors or when the device state may be stale.\n * The next operation will re-discover and re-connect automatically.\n */\n resetState(): void {\n this._discoveredDevices.clear();\n this._sessions.clear();\n this._connectingPromise = null;\n this._uiRegistry.reset();\n this._jobQueue.clear();\n this._btcHighIndexConfirmedThisSession = false;\n }\n\n async dispose(): Promise<void> {\n this._uiRegistry.reset();\n this._jobQueue.clear();\n this.unregisterEventListeners();\n this.connector.reset();\n this._discoveredDevices.clear();\n this._sessions.clear();\n this._btcHighIndexConfirmedThisSession = false;\n this.emitter.removeAllListeners();\n }\n\n uiResponse(response: UiResponseEvent): void {\n this._uiRegistry.resolve(response.type, response.payload);\n }\n\n // ---------------------------------------------------------------------------\n // Device management\n // ---------------------------------------------------------------------------\n\n async searchDevices(options?: SearchDevicesOptions): Promise<DeviceInfo[]> {\n if (options?.resetSession) {\n this._doConnectAbortController?.abort();\n this._sessions.clear();\n this._connectingPromise = null;\n this._doConnectAbortController = null;\n this._btcHighIndexConfirmedThisSession = false;\n }\n\n await this._ensureDevicePermission();\n\n const devices = await this.connector.searchDevices();\n\n // Replace cache with this round's raw result. DMK paths used as connectId\n // on USB are ephemeral — incremental writes leave stale entries.\n this._discoveredDevices.clear();\n for (const d of devices) {\n if (d.connectId) {\n this._discoveredDevices.set(d.connectId, this.connectorDeviceToDeviceInfo(d));\n }\n }\n\n if (this._discoveredDevices.size === 0) {\n await this._ensureDevicePermission();\n }\n\n debugLog(\n `[LedgerAdapter] searchDevices() return count=${this._discoveredDevices.size} ids=[${[\n ...this._discoveredDevices.keys(),\n ].join(',')}]`\n );\n return Array.from(this._discoveredDevices.values());\n }\n\n // USB single-session invariant: evict all sessions, best-effort (see connectDevice).\n private async _evictAllSessions(): Promise<void> {\n if (this._sessions.size === 0) return;\n const stale = [...this._sessions.values()];\n this._sessions.clear();\n for (const sid of stale) {\n try {\n await this.connector.disconnect(sid);\n } catch {\n // best-effort\n }\n }\n }\n\n // Layer 2 retry budget after connection-class error. Each round delegates\n // to Layer 1 (which owns the unlock prompt). Layer 2 never emits UI itself.\n private static readonly MAX_BUSINESS_RETRY_BUDGET = 3;\n\n // Stuck-app (APDU 0x6901) retry pause. Ledger Stax often returns 6901 when\n // OpenAppCommand lands mid-transition right after CloseApp; a short wait\n // lets the device finish its UI animation before we retry once.\n private static readonly STUCK_APP_RETRY_DELAY_MS = 500;\n\n // Layer 1 confirm budget. After N failed Confirm cycles (user keeps clicking\n // Confirm but device never shows up / never unlocks), throw DeviceNotFound\n // instead of looping forever.\n private static readonly MAX_DOCONNECT_CONFIRMS = 3;\n\n // Cached cancel reason — used as fallback when signal.reason isn't\n // populated by the runtime (Hermes/RN). Set in cancel(), cleared shortly.\n private _lastCancelReason: Error | undefined;\n\n private static _createDeviceBusyError(method: string): Error {\n return Object.assign(new Error(`Ledger device is busy while calling ${method}`), {\n code: HardwareErrorCode.DeviceBusy,\n });\n }\n\n async connectDevice(connectId: string): Promise<Response<string>> {\n try {\n if (isLedgerBleConnectionType(this.connector.connectionType) && !connectId) {\n throw Object.assign(new Error('Ledger BLE connectId is required.'), {\n code: HardwareErrorCode.DeviceNotFound,\n });\n }\n\n // USB single-session invariant: evict any stale session before opening\n // a new one — guards ensureConnected's ambient fallback against ghosts.\n if (!isLedgerBleConnectionType(this.connector.connectionType)) {\n await this._evictAllSessions();\n }\n\n await this._ensureDevicePermission(connectId);\n\n const session = await this.connector.connect(connectId);\n this._sessions.set(connectId, session.sessionId);\n\n if (session.deviceInfo) {\n this._discoveredDevices.set(connectId, session.deviceInfo);\n }\n\n return success(connectId);\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async disconnectDevice(connectId: string): Promise<void> {\n const sessionId = this._sessions.get(connectId);\n if (sessionId) {\n await this.connector.disconnect(sessionId);\n this._sessions.delete(connectId);\n }\n }\n\n async getDeviceInfo(connectId: string, deviceId: string): Promise<Response<DeviceInfo>> {\n await this._ensureDevicePermission(connectId, deviceId);\n\n // Look up the device in the cache populated by event handlers / searchDevices.\n // Try connectId first (the USB path), then fall back to scanning by deviceId.\n const cached =\n this._discoveredDevices.get(connectId) ??\n Array.from(this._discoveredDevices.values()).find(d => d.deviceId === deviceId);\n\n if (cached) {\n return success(cached);\n }\n\n return failure(\n HardwareErrorCode.DeviceNotFound,\n 'Device not found in cache. Call searchDevices() or wait for a device-connected event first.'\n );\n }\n\n getSupportedChains(): ChainCapability[] {\n return ['evm', 'btc', 'sol', 'tron'];\n }\n\n // ---------------------------------------------------------------------------\n // Chain call helper\n // ---------------------------------------------------------------------------\n\n private async callChain<T>(\n connectId: string,\n deviceId: string,\n chain: string,\n method: string,\n params: unknown,\n commonParams?: ICommonCallParams,\n skipFingerprint = false\n ): Promise<Response<T>> {\n try {\n const result = await this.connectorCall(\n connectId,\n method,\n params,\n {\n chain: chain as ChainForFingerprint,\n deviceId,\n skipFingerprint,\n },\n undefined,\n commonParams\n );\n return success(result as T);\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n // ---------------------------------------------------------------------------\n // EVM chain methods\n // ---------------------------------------------------------------------------\n\n evmGetAddress(\n connectId: string,\n deviceId: string,\n params: EvmGetAddressParams,\n commonParams?: ICommonCallParams\n ) {\n return this.callChain<EvmAddress>(\n connectId,\n deviceId,\n 'evm',\n 'evmGetAddress',\n params,\n commonParams\n );\n }\n\n evmSignTransaction(\n connectId: string,\n deviceId: string,\n params: EvmSignTxParams,\n commonParams?: ICommonCallParams\n ) {\n return this.callChain<EvmSignedTx>(\n connectId,\n deviceId,\n 'evm',\n 'evmSignTransaction',\n params,\n commonParams\n );\n }\n\n evmSignMessage(\n connectId: string,\n deviceId: string,\n params: EvmSignMsgParams,\n commonParams?: ICommonCallParams\n ) {\n return this.callChain<EvmSignature>(\n connectId,\n deviceId,\n 'evm',\n 'evmSignMessage',\n params,\n commonParams\n );\n }\n\n evmSignTypedData(\n connectId: string,\n deviceId: string,\n params: EvmSignTypedDataParams,\n commonParams?: ICommonCallParams\n ) {\n return this.callChain<EvmSignature>(\n connectId,\n deviceId,\n 'evm',\n 'evmSignTypedData',\n params,\n commonParams\n );\n }\n\n // ---------------------------------------------------------------------------\n // BTC chain methods\n // ---------------------------------------------------------------------------\n\n btcGetAddress(\n connectId: string,\n deviceId: string,\n params: BtcGetAddressParams,\n commonParams?: ICommonCallParams\n ) {\n return this.callChain<BtcAddress>(\n connectId,\n deviceId,\n 'btc',\n 'btcGetAddress',\n params,\n commonParams\n );\n }\n\n btcGetPublicKey(\n connectId: string,\n deviceId: string,\n params: BtcGetPublicKeyParams,\n commonParams?: ICommonCallParams\n ) {\n return this.callChain<BtcPublicKey>(\n connectId,\n deviceId,\n 'btc',\n 'btcGetPublicKey',\n params,\n commonParams\n );\n }\n\n btcSignTransaction(\n connectId: string,\n deviceId: string,\n params: BtcSignTxParams,\n commonParams?: ICommonCallParams\n ) {\n return this.callChain<BtcSignedTx>(\n connectId,\n deviceId,\n 'btc',\n 'btcSignTransaction',\n params,\n commonParams\n );\n }\n\n btcSignPsbt(\n connectId: string,\n deviceId: string,\n params: BtcSignPsbtParams,\n commonParams?: ICommonCallParams\n ) {\n return this.callChain<BtcSignedPsbt>(\n connectId,\n deviceId,\n 'btc',\n 'btcSignPsbt',\n params,\n commonParams\n );\n }\n\n btcSignMessage(\n connectId: string,\n deviceId: string,\n params: BtcSignMsgParams,\n commonParams?: ICommonCallParams\n ) {\n return this.callChain<BtcSignature>(\n connectId,\n deviceId,\n 'btc',\n 'btcSignMessage',\n params,\n commonParams\n );\n }\n\n btcGetMasterFingerprint(connectId: string, deviceId: string, commonParams?: ICommonCallParams) {\n return this.callChain<{ masterFingerprint: string }>(\n connectId,\n deviceId,\n 'btc',\n 'btcGetMasterFingerprint',\n {},\n commonParams\n );\n }\n\n // ---------------------------------------------------------------------------\n // SOL chain methods\n // ---------------------------------------------------------------------------\n\n solGetAddress(\n connectId: string,\n deviceId: string,\n params: SolGetAddressParams,\n commonParams?: ICommonCallParams\n ) {\n return this.callChain<SolAddress>(\n connectId,\n deviceId,\n 'sol',\n 'solGetAddress',\n params,\n commonParams\n );\n }\n\n solSignTransaction(\n connectId: string,\n deviceId: string,\n params: SolSignTxParams,\n commonParams?: ICommonCallParams\n ) {\n return this.callChain<SolSignedTx>(\n connectId,\n deviceId,\n 'sol',\n 'solSignTransaction',\n params,\n commonParams\n );\n }\n\n solSignMessage(\n connectId: string,\n deviceId: string,\n params: SolSignMsgParams,\n commonParams?: ICommonCallParams\n ) {\n return this.callChain<SolSignature>(\n connectId,\n deviceId,\n 'sol',\n 'solSignMessage',\n params,\n commonParams\n );\n }\n\n // ---------------------------------------------------------------------------\n // TRON chain methods\n // ---------------------------------------------------------------------------\n\n tronGetAddress(\n connectId: string,\n deviceId: string,\n params: TronGetAddressParams,\n commonParams?: ICommonCallParams\n ) {\n return this.callChain<TronAddress>(\n connectId,\n deviceId,\n 'tron',\n 'tronGetAddress',\n params,\n commonParams\n );\n }\n\n tronSignTransaction(\n connectId: string,\n deviceId: string,\n params: TronSignTxParams,\n commonParams?: ICommonCallParams\n ) {\n return this.callChain<TronSignedTx>(\n connectId,\n deviceId,\n 'tron',\n 'tronSignTransaction',\n params,\n commonParams\n );\n }\n\n tronSignMessage(\n connectId: string,\n deviceId: string,\n params: TronSignMsgParams,\n commonParams?: ICommonCallParams\n ) {\n return this.callChain<TronSignature>(\n connectId,\n deviceId,\n 'tron',\n 'tronSignMessage',\n params,\n commonParams\n );\n }\n\n // ---------------------------------------------------------------------------\n // App management — OS-level Ledger app install / list. Bypasses fingerprint\n // and chain-handler dispatch; installApp progress is forwarded to the adapter\n // emitter via 'ui-event' AppInstallProgress events.\n // ---------------------------------------------------------------------------\n\n async installApp(connectId: string, appName: string): Promise<Response<void>> {\n try {\n // Progress is emitted from the connector via a 'ui-event'\n // AppInstallProgress variant (see uiEventForwarder); no callback is\n // passed here so installApp params stay fully serializable across\n // IHardwareBridge.\n await this.connectorCall(connectId, 'installApp', { appName });\n return success(undefined);\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async listInstalledApps(connectId: string): Promise<Response<AppMetadata[]>> {\n try {\n const result = await this.connectorCall(connectId, 'listInstalledApps', {});\n return success(result as AppMetadata[]);\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async listAvailableApps(connectId: string): Promise<Response<AppMetadata[]>> {\n try {\n const result = await this.connectorCall(connectId, 'listAvailableApps', {});\n return success(result as AppMetadata[]);\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async getLedgerFirmwareVersion(connectId: string): Promise<Response<FirmwareVersion>> {\n try {\n const result = await this.connectorCall(connectId, 'getFirmwareVersion', {});\n return success(result as FirmwareVersion);\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n async getLedgerDeviceInfo(connectId: string): Promise<Response<LedgerDeviceInfo>> {\n try {\n const result = await this.connectorCall(connectId, 'getDeviceInfo', {});\n return success(result as LedgerDeviceInfo);\n } catch (err) {\n return this.errorToFailure(err);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Events\n // ---------------------------------------------------------------------------\n\n on<K extends keyof HardwareEventMap>(\n event: K,\n listener: (event: HardwareEventMap[K]) => void\n ): void;\n\n on(event: string, listener: DeviceEventListener): void;\n\n on(event: string, listener: (event: HardwareEvent) => void): void {\n this.emitter.on(event, listener);\n }\n\n off<K extends keyof HardwareEventMap>(\n event: K,\n listener: (event: HardwareEventMap[K]) => void\n ): void;\n\n off(event: string, listener: DeviceEventListener): void;\n\n off(event: string, listener: (event: HardwareEvent) => void): void {\n this.emitter.off(event, listener);\n }\n\n cancel(connectId?: string): void {\n const userAbortReason = Object.assign(new Error('User aborted operation'), {\n code: HardwareErrorCode.UserAborted,\n _tag: ERROR_TAG.UserAborted,\n });\n\n // Hermes/RN polyfills don't always populate signal.reason from\n // abortController.abort(reason). Cache the reason here so _abortable\n // can fall back to it. Cleared after a short window so a stale reason\n // can't taint an unrelated abort later.\n this._lastCancelReason = userAbortReason;\n setTimeout(() => {\n if (this._lastCancelReason === userAbortReason) {\n this._lastCancelReason = undefined;\n }\n }, 2000);\n\n this._uiRegistry.cancel();\n\n // No-connectId path collateral-cancels concurrent silent jobs (known\n // limitation; needs per-job foreground flag to fix).\n if (connectId) {\n this._jobQueue.cancelActiveAndPending(connectId, userAbortReason);\n } else {\n this._jobQueue.cancelActiveAndPending(undefined, userAbortReason);\n }\n\n if (connectId) {\n const sessionId = this._sessions.get(connectId) ?? connectId;\n void this.connector.cancel(sessionId);\n } else {\n for (const sid of this._sessions.values()) void this.connector.cancel(sid);\n }\n\n // Snapshot guard: only abort if connect is actually in flight (avoids\n // hitting a NEW controller from a restart between resolve and re-entry).\n if (this._connectingPromise) {\n this._doConnectAbortController?.abort(userAbortReason);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Chain fingerprint\n // ---------------------------------------------------------------------------\n\n async getChainFingerprint(\n connectId: string,\n deviceId: string,\n chain: ChainForFingerprint\n ): Promise<Response<string>> {\n try {\n const fingerprint = await this._computeChainFingerprint(chain, (method, params) =>\n this.connectorCall(connectId, method, params, undefined, deviceId)\n );\n return success(fingerprint);\n } catch (err) {\n debugError('[LedgerAdapter] getChainFingerprint error:', chain, err);\n return this.errorToFailure(err);\n }\n }\n\n /**\n * Verify fingerprint using an existing sessionId directly.\n * Safe to call inside connectorCall without causing queue deadlock.\n */\n private async _verifyDeviceFingerprintWithSession(\n sessionId: string,\n deviceId: string,\n chain: ChainForFingerprint\n ): Promise<IFingerprintVerifyResult> {\n if (!deviceId) return { success: true };\n\n try {\n const fingerprint = await this._computeChainFingerprint(chain, (method, params) =>\n this._callConnector(sessionId, method, params)\n );\n if (fingerprint === deviceId) {\n return { success: true };\n }\n return { success: false, expected: deviceId, actual: fingerprint };\n } catch (err) {\n const mapped = mapLedgerError(err);\n if (\n mapped.code === HardwareErrorCode.WrongApp ||\n mapped.code === HardwareErrorCode.DeviceLocked\n ) {\n return { success: true };\n }\n throw err;\n }\n }\n\n /**\n * Compute the chain fingerprint via a caller-supplied call strategy.\n *\n * Chains with a native device-side identity primitive (BTC → BIP32 master\n * fingerprint) short-circuit at the top and return it verbatim, so the value\n * stays reusable for higher-level use (BIP380 descriptors, PSBT signing).\n *\n * All other chains derive a fixed-path address and run it through\n * `deriveDeviceFingerprint` to produce an opaque seed identifier.\n *\n * The two callers (`getChainFingerprint` / `_verifyDeviceFingerprintWithSession`)\n * differ only in the underlying call mechanism, which is injected as `callMethod`\n * to avoid queue deadlocks when running inside `connectorCall`.\n */\n private async _computeChainFingerprint(\n chain: ChainForFingerprint,\n callMethod: (method: string, params: unknown) => Promise<unknown>\n ): Promise<string> {\n // BTC: dedicated device call returns the BIP32 master fingerprint already\n // in the canonical 8-hex form — no further hashing.\n if (chain === 'btc') {\n const result = (await callMethod('btcGetMasterFingerprint', {})) as {\n masterFingerprint: string;\n };\n return result.masterFingerprint;\n }\n\n const path = CHAIN_FINGERPRINT_PATHS[chain];\n let address: string;\n if (chain === 'evm') {\n // Lowercase per deriveDeviceFingerprint's canonical-form contract.\n address = (\n (await callMethod('evmGetAddress', { path, showOnDevice: false })) as {\n address: string;\n }\n ).address.toLowerCase();\n } else if (chain === 'sol') {\n address = (\n (await callMethod('solGetAddress', { path, showOnDevice: false })) as {\n address: string;\n }\n ).address;\n } else if (chain === 'tron') {\n address = (\n (await callMethod('tronGetAddress', { path, showOnDevice: false })) as {\n address: string;\n }\n ).address;\n } else {\n throw new Error(`Unsupported chain for fingerprint: ${chain as string}`);\n }\n\n return deriveDeviceFingerprint(address);\n }\n\n // ---------------------------------------------------------------------------\n // Private helpers\n // ---------------------------------------------------------------------------\n\n /**\n * Ensure at least one device is connected and return a valid connectId.\n *\n * - If a session already exists for the given connectId, reuse it.\n * - If ANY session exists (Ledger IDs are ephemeral), reuse it.\n * - Otherwise: search → exactly 1 USB device auto-connects; multiple or none throws.\n */\n // Mutex for ensureConnected — prevents concurrent calls from establishing duplicate connections\n private _connectingPromise: Promise<string> | null = null;\n\n // Ledger WebUSB won't expose a locked device, so we can't auto-detect unlock.\n // The user must press Confirm after unlocking, which triggers a search retry.\n // If `signal` is provided, an abort cancels the pending UI request so the\n // registry slot is released and a stale RECEIVE_DEVICE_CONNECT won't land in\n // a future request.\n private async _waitForDeviceConnect(signal?: AbortSignal): Promise<void> {\n if (signal?.aborted) {\n LedgerAdapter._throwIfAborted(signal);\n }\n\n // Register the wait FIRST. A synchronous consumer that calls `uiResponse`\n // inside the emit handler would otherwise resolve before the registry\n // slot exists, and the response would be silently dropped (see\n // UiRequestRegistry.resolve early-return on missing entry).\n const waitPromise = this._uiRegistry.wait<{ confirmed: boolean }>(\n UI_REQUEST.REQUEST_DEVICE_CONNECT\n );\n\n this.emitter.emit(UI_REQUEST.REQUEST_DEVICE_CONNECT, {\n type: UI_REQUEST.REQUEST_DEVICE_CONNECT,\n payload: {\n vendor: 'ledger',\n reason: 'device-not-found',\n message: 'Please connect and unlock your Ledger device',\n },\n });\n\n let payload: { confirmed: boolean } | undefined;\n try {\n if (signal) {\n const onAbort = () => {\n this._uiRegistry.cancel(UI_REQUEST.REQUEST_DEVICE_CONNECT);\n };\n signal.addEventListener('abort', onAbort, { once: true });\n try {\n payload = await waitPromise;\n } finally {\n signal.removeEventListener('abort', onAbort);\n }\n } else {\n payload = await waitPromise;\n }\n } catch (err) {\n // External cancel (signal abort / jobQueue cancel) — app's atom may\n // still be set, so signal it to drop the dialog.\n this.emitter.emit(UI_REQUEST.CLOSE_UI_WINDOW, {\n type: UI_REQUEST.CLOSE_UI_WINDOW,\n payload: {},\n });\n // Re-tag as UserAborted so upstream classifiers stop the batch.\n throw Object.assign(new Error('User cancelled Ledger connection'), {\n _tag: ERROR_TAG.UserAborted,\n code: HardwareErrorCode.UserAborted,\n cause: err,\n });\n }\n\n if (!payload?.confirmed) {\n throw Object.assign(new Error('User cancelled Ledger connection'), {\n _tag: ERROR_TAG.UserAborted,\n code: HardwareErrorCode.UserAborted,\n });\n }\n\n // BLE peripheral needs a moment to settle after user unlocks the device.\n // Without this delay, the immediate searchDevices() following Confirm\n // often returns 0, forcing another loop iteration.\n await new Promise<void>(resolve => {\n setTimeout(resolve, 800);\n });\n }\n\n /**\n * Decide whether a BTC pubkey call needs `showOnDevice=true` because of\n * the BTC App's account-index policy, asking the user once per session.\n *\n * Returns the params to pass through (with `showOnDevice` possibly\n * promoted), or `null` if the user declined.\n */\n private async _gateBtcHighIndex(\n params: BtcGetPublicKeyParams\n ): Promise<BtcGetPublicKeyParams | null> {\n const accountIndex = btcAccountIndexFromPath(params.path);\n if (params.showOnDevice) return params;\n if (accountIndex === null || accountIndex < BTC_HIGH_INDEX_THRESHOLD) {\n return params;\n }\n if (this._btcHighIndexConfirmedThisSession) {\n return { ...params, showOnDevice: true };\n }\n const confirmed = await this._waitForBtcHighIndexConfirm(params.path, accountIndex);\n if (!confirmed) return null;\n this._btcHighIndexConfirmedThisSession = true;\n return { ...params, showOnDevice: true };\n }\n\n private async _waitForBtcHighIndexConfirm(path: string, accountIndex: number): Promise<boolean> {\n // Register the wait FIRST. A synchronous consumer that calls `uiResponse`\n // inside the emit handler would otherwise resolve before the registry\n // slot exists, and the response would be silently dropped (see\n // UiRequestRegistry.resolve early-return on missing entry).\n const waitPromise = this._uiRegistry.wait<{ confirmed: boolean }>(\n UI_REQUEST.REQUEST_BTC_HIGH_INDEX_CONFIRM\n );\n\n this.emitter.emit(UI_REQUEST.REQUEST_BTC_HIGH_INDEX_CONFIRM, {\n type: UI_REQUEST.REQUEST_BTC_HIGH_INDEX_CONFIRM,\n payload: {\n vendor: 'ledger',\n path,\n accountIndex,\n },\n });\n\n try {\n const payload = await waitPromise;\n return !!payload?.confirmed;\n } catch (err) {\n this.emitter.emit(UI_REQUEST.CLOSE_UI_WINDOW, {\n type: UI_REQUEST.CLOSE_UI_WINDOW,\n payload: {},\n });\n return false;\n }\n }\n\n // Ask the user whether to install a missing app (autoInstallApp flow).\n // Same register-then-emit ordering as the BTC high-index gate.\n private async _waitForInstallAppConfirm(appName: string): Promise<boolean> {\n const waitPromise = this._uiRegistry.wait<{ confirmed: boolean }>(\n UI_REQUEST.REQUEST_INSTALL_APP\n );\n\n this.emitter.emit(UI_REQUEST.REQUEST_INSTALL_APP, {\n type: UI_REQUEST.REQUEST_INSTALL_APP,\n payload: { vendor: 'ledger', appName },\n });\n\n try {\n const payload = await waitPromise;\n return !!payload?.confirmed;\n } catch (err) {\n this.emitter.emit(UI_REQUEST.CLOSE_UI_WINDOW, {\n type: UI_REQUEST.CLOSE_UI_WINDOW,\n payload: {},\n });\n return false;\n }\n }\n\n // Layer 1 entry. Caller signal only races the outer awaiter; the shared\n // `_doConnect` runs under its own internal controller so caller A's cancel\n // doesn't kill caller B's await.\n private async ensureConnected(\n connectId: string | undefined,\n signal: AbortSignal,\n allowUsbEphemeralFallback = false\n ): Promise<string> {\n if (signal.aborted) LedgerAdapter._throwIfAborted(signal);\n\n if (isLedgerBleConnectionType(this.connector.connectionType) && !connectId) {\n throw Object.assign(new Error('Ledger BLE connectId is required.'), {\n code: HardwareErrorCode.DeviceNotFound,\n });\n }\n\n if (connectId && this._sessions.has(connectId)) return connectId;\n // Ambient fallback only when the caller gave no target. On an explicit\n // connectId miss, re-resolve THAT device via _doConnect — never route to\n // the first session entry (a stale entry for B once made A's calls hit B).\n if (!connectId && this._sessions.size > 0) {\n // Fail loud rather than route to a wrong device; connectDevice evicts\n // first, so size>1 here should be impossible.\n if (!isLedgerBleConnectionType(this.connector.connectionType) && this._sessions.size > 1) {\n throw Object.assign(\n new Error(\n 'Ledger USB session invariant violated: more than one session is active. Please reconnect the device.'\n ),\n { code: HardwareErrorCode.DeviceOneDeviceOnly }\n );\n }\n return this._sessions.keys().next().value as string;\n }\n\n if (!this._connectingPromise) {\n this._doConnectAbortController = new AbortController();\n const innerSignal = this._doConnectAbortController.signal;\n this._connectingPromise = (async () => {\n try {\n return await this._doConnect(innerSignal, connectId, allowUsbEphemeralFallback);\n } finally {\n this._connectingPromise = null;\n this._doConnectAbortController = null;\n }\n })();\n }\n\n return this._abortable(signal, this._connectingPromise);\n }\n\n // Layer 1 main loop — the ONLY place in SDK that emits unlock dialog.\n // Bounded by MAX_DOCONNECT_CONFIRMS — after N Confirms with no progress,\n // throw DeviceNotFound so the user is kicked out of the loop.\n private async _doConnect(\n internalSignal: AbortSignal,\n targetConnectId?: string,\n allowUsbEphemeralFallback = false\n ): Promise<string> {\n if (isLedgerBleConnectionType(this.connector.connectionType) && targetConnectId) {\n try {\n return await this._connectDeviceOrThrow(targetConnectId);\n } catch (err) {\n if (\n !isDeviceLockedError(err) &&\n !isDeviceNotAdvertisingError(err) &&\n !isDeviceDisconnectedError(err)\n ) {\n throw err;\n }\n this._discoveredDevices.delete(targetConnectId);\n if (isDeviceDisconnectedError(err)) {\n try {\n this.connector.reset?.();\n } catch {\n // best-effort\n }\n }\n }\n }\n\n let confirms = 0;\n while (!internalSignal.aborted) {\n // Tell consumers we're actively scanning. Re-emitted at every iteration\n // so the toast comes back after `_waitForDeviceConnect` closes its\n // dialog — the dialog overrides the searching toast while open, and\n // the next round needs an explicit signal to bring it back.\n this.emitter.emit('ui-event', {\n type: EConnectorInteraction.Searching,\n payload: { sessionId: '' },\n });\n let devices = await this.searchDevices();\n\n // First scan empty? Retry — BLE state can be flaky right after a\n // PairingRefused / Disconnect / fresh app restart, and ble-plx scans\n // sometimes miss a device that's actually advertising. Worth a few\n // extra seconds before bothering the user with a dialog.\n if (devices.length === 0) {\n for (let i = 0; i < 3 && !internalSignal.aborted; i += 1) {\n await new Promise<void>(resolve => {\n setTimeout(resolve, 1000);\n });\n devices = await this.searchDevices();\n if (devices.length > 0) break;\n }\n }\n\n if (devices.length > 0) {\n try {\n return await this._connectFirstOrSelect(\n devices,\n targetConnectId,\n allowUsbEphemeralFallback\n );\n } catch (err) {\n // PairingFailure / DeviceMismatch / unclassified → throw out, no\n // Layer 1 retry. PairingRefused = user declined system pair prompt\n // / didn't confirm on device — edge case, let upstream surface it.\n // Locked / NotAdvertising / Disconnected stay as recoverable since\n // they often clear themselves between attempts.\n if (\n !isDeviceLockedError(err) &&\n !isDeviceNotAdvertisingError(err) &&\n !isDeviceDisconnectedError(err)\n ) {\n throw err;\n }\n this._discoveredDevices.clear();\n if (isDeviceDisconnectedError(err)) {\n try {\n this.connector.reset?.();\n } catch {\n // best-effort\n }\n }\n }\n }\n\n if (confirms >= LedgerAdapter.MAX_DOCONNECT_CONFIRMS) {\n throw Object.assign(\n new Error(\n 'Device not connected after multiple attempts. Please ensure your Ledger is awake, unlocked, and in range, then try again.'\n ),\n { code: HardwareErrorCode.DeviceNotFound }\n );\n }\n\n await this._waitForDeviceConnect(internalSignal);\n confirms += 1;\n }\n LedgerAdapter._throwIfAborted(internalSignal);\n // Unreachable — _throwIfAborted always throws when aborted.\n throw new Error('_doConnect aborted');\n }\n\n private async _connectFirstOrSelect(\n devices: DeviceInfo[],\n targetConnectId?: string,\n allowUsbEphemeralFallback = false\n ): Promise<string> {\n if (targetConnectId) {\n const target = devices.find(\n d => d.connectId === targetConnectId || d.deviceId === targetConnectId\n );\n if (target) {\n return this._connectDeviceOrThrow(target.connectId);\n }\n\n // Decision: a stale USB target + fresh search returning exactly one\n // Ledger is not proof that the sole Ledger is the original device. It\n // might be A after a replug (safe to recover), or B after A was unplugged\n // (wrong-device risk).\n //\n // We only take this recovery path when the business call supplied a\n // stable wallet fingerprint (`deviceId`) and did not opt out of\n // fingerprint checks. The connection is then provisional: the caller must\n // run `_verifyDeviceFingerprintWithSession` before sending the real APDU.\n // Calls without that identity check fail closed with DeviceNotFound so\n // the host can ask the user to reconnect/select again.\n if (\n !isLedgerBleConnectionType(this.connector.connectionType) &&\n devices.length === 1 &&\n allowUsbEphemeralFallback\n ) {\n debugLog(\n `[LedgerAdapter] target ${targetConnectId} not in fresh enumeration; ` +\n `accepting sole USB device ${devices[0].connectId} for fingerprint-verified recovery`\n );\n return this._connectDeviceOrThrow(devices[0].connectId);\n }\n\n const err = Object.assign(new Error(`Target Ledger unavailable: ${targetConnectId}`), {\n code: HardwareErrorCode.DeviceNotFound,\n }) as Error & { _tag?: string };\n if (isLedgerBleConnectionType(this.connector.connectionType)) {\n err._tag = ERROR_TAG.DeviceNotAdvertising;\n }\n throw err;\n }\n\n if (isLedgerBleConnectionType(this.connector.connectionType)) {\n throw Object.assign(new Error('Ledger BLE connectId is required.'), {\n code: HardwareErrorCode.DeviceNotFound,\n });\n }\n\n // No target + multiple USB devices: refuse to auto-pick by ephemeral\n // connectId (the multi-device drift bug). Caller must specify which device.\n if (devices.length > 1) {\n throw createMultipleUsbLedgerDevicesError();\n }\n\n if (devices.length !== 1) {\n throw Object.assign(new Error('Ledger device not found.'), {\n code: HardwareErrorCode.DeviceNotFound,\n });\n }\n\n return this._connectDeviceOrThrow(devices[0].connectId);\n }\n\n private async _connectDeviceOrThrow(chosenConnectId: string): Promise<string> {\n const result = await this.connectDevice(chosenConnectId);\n if (!result.success) {\n // _tag must survive — _doConnect's catch is _tag-based.\n const payload = result.payload as { error: string; code: number; _tag?: string };\n const rethrow = Object.assign(new Error(payload.error), {\n code: payload.code,\n }) as Error & { _tag?: string };\n if (payload._tag !== undefined) {\n rethrow._tag = payload._tag;\n }\n throw rethrow;\n }\n return chosenConnectId;\n }\n\n /**\n * Call the connector with automatic session resolution and disconnect retry.\n *\n * 1. Resolves a valid connectId via ensureConnected()\n * 2. Looks up sessionId from _sessions\n * 3. Calls connector.call()\n * 4. On disconnect error: clears stale session, re-connects, retries once\n */\n /**\n * Unwrap a `ConnectorCallResult` back into the throw-based control flow this\n * class relies on. On failure, rehydrate a FLAT Error (lifting `params.*`\n * back to own-properties) so the downstream recovery predicates\n * (`isStuckAppStateError`, `isDeviceLockedError`, …) and `mapLedgerError`\n * (which read `err._tag` / `err.code` / `err.appName` / `err.originalError`)\n * keep working exactly as before — the Result shape is confined to the\n * connector boundary.\n */\n private _unwrapConnectorResult(result: ConnectorCallResult): unknown {\n if (result.success) return result.payload;\n throw rehydrateConnectorError(result.error);\n }\n\n /**\n * `connector.call` + result unwrap, optionally raced against an abort\n * signal. Returns the call payload or throws the rehydrated error. All\n * `this.connector.call` usage goes through here so the Result→throw seam\n * lives in one place.\n */\n private async _callConnector(\n sessionId: string,\n method: string,\n params: unknown,\n signal?: AbortSignal\n ): Promise<unknown> {\n const promise = this.connector.call(sessionId, method, params);\n const result = signal ? await this._abortable(signal, promise) : await promise;\n return this._unwrapConnectorResult(result);\n }\n\n private async connectorCall(\n connectId: string,\n method: string,\n params: unknown,\n fingerprint?: ConnectorCallFingerprint,\n permissionDeviceId?: string,\n commonParams?: ICommonCallParams\n ): Promise<unknown> {\n debugLog('[LedgerAdapter] connectorCall:', method, 'connectId:', connectId || '(empty)');\n\n // Queue is global serial; deviceId is just a label for inspection / cancellation.\n const queueKey = connectId || '__ledger_default__';\n\n return this._jobQueue.enqueue(\n queueKey,\n async signal =>\n this._runConnectorCall(\n connectId,\n method,\n params,\n signal,\n fingerprint,\n permissionDeviceId,\n commonParams\n ),\n {\n label: method,\n rejectIfBusy: true,\n busyError: LedgerAdapter._createDeviceBusyError(method),\n }\n );\n }\n\n /**\n * Race a promise against an abort signal. On abort, rejects with\n * signal.reason → instance _lastCancelReason → generic Error('Aborted').\n */\n private _abortable<T>(signal: AbortSignal, promise: Promise<T>): Promise<T> {\n const getAbortReason = () =>\n (signal as AbortSignal & { reason?: unknown }).reason ??\n this._lastCancelReason ??\n new Error('Aborted');\n\n if (signal.aborted) {\n return Promise.reject(getAbortReason());\n }\n return new Promise<T>((resolve, reject) => {\n const onAbort = () => {\n reject(getAbortReason());\n };\n signal.addEventListener('abort', onAbort, { once: true });\n promise.then(\n value => {\n signal.removeEventListener('abort', onAbort);\n resolve(value);\n },\n err => {\n signal.removeEventListener('abort', onAbort);\n reject(err);\n }\n );\n });\n }\n\n /** Throw an AbortError if signal is already aborted. */\n private static _throwIfAborted(signal: AbortSignal): void {\n if (signal.aborted) {\n throw (signal as AbortSignal & { reason?: unknown }).reason ?? new Error('Aborted');\n }\n }\n\n /** Actual work done under the job queue — connection, fingerprint, call, and recovery. */\n private async _runConnectorCall(\n connectId: string,\n method: string,\n params: unknown,\n signal: AbortSignal,\n fingerprint?: ConnectorCallFingerprint,\n permissionDeviceId?: string,\n commonParams?: ICommonCallParams\n ): Promise<unknown> {\n LedgerAdapter._throwIfAborted(signal);\n await this._ensureDevicePermission(\n connectId,\n permissionDeviceId ?? fingerprint?.deviceId,\n signal\n );\n LedgerAdapter._throwIfAborted(signal);\n let effectiveParams = params;\n if (method === 'btcGetPublicKey') {\n const gatedParams = await this._gateBtcHighIndex(params as BtcGetPublicKeyParams);\n if (gatedParams === null) {\n throw Object.assign(new Error('User cancelled BTC high-index confirmation'), {\n _tag: ERROR_TAG.UserAborted,\n code: HardwareErrorCode.UserAborted,\n });\n }\n effectiveParams = gatedParams;\n }\n\n const allowUsbEphemeralFallback = !!fingerprint?.deviceId && !fingerprint.skipFingerprint;\n\n // Wrap ensureConnected in _abortable so an abort during device discovery /\n // user-connect UI wait rejects this caller immediately. The underlying\n // _doConnect / _connectingPromise is shared across callers and continues\n // running — other concurrent callers aren't affected.\n const resolvedConnectId = await this.ensureConnected(\n connectId,\n signal,\n allowUsbEphemeralFallback\n );\n const sessionId = this._sessions.get(resolvedConnectId);\n if (!sessionId) {\n throw Object.assign(new Error('Auto-connect succeeded but no session found'), {\n _tag: ERROR_TAG.DeviceSessionNotFound,\n });\n }\n\n // Fingerprint verification inside the session — atomic with the actual call\n try {\n // Fingerprint verification lives inside the same try/catch as the main\n // call so that transport-level errors raised by `_computeChainFingerprint`\n // (e.g. \"Device communication interrupted\") flow through the recovery\n // path below — clearing session + resetting connector. Without this,\n // a stuck DMK transport during fingerprint check leaks the dead\n // session to subsequent retries (they keep using the same broken\n // sessionId until the user replugs).\n if (fingerprint && !fingerprint.skipFingerprint && fingerprint.deviceId) {\n const fp = await this._abortable(\n signal,\n this._verifyDeviceFingerprintWithSession(\n sessionId,\n fingerprint.deviceId,\n fingerprint.chain\n )\n );\n if (!fp.success) {\n throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {\n code: HardwareErrorCode.DeviceMismatch,\n });\n }\n }\n return await this._callConnector(sessionId, method, effectiveParams, signal);\n } catch (err) {\n // If the abort fired, surface it directly — skip recovery paths.\n if (signal.aborted) throw err;\n const errObj = err as Record<string, unknown> | null | undefined;\n debugLog('[LedgerAdapter] connectorCall error:', method, {\n message: errObj?.message,\n _tag: errObj?._tag,\n errorCode: errObj?.errorCode,\n statusCode: errObj?.statusCode,\n isDisconnected: isDeviceDisconnectedError(err),\n isLocked: isDeviceLockedError(err),\n isNotAdvertising: isDeviceNotAdvertisingError(err),\n isStuckApp: isStuckAppStateError(err),\n });\n\n // Auto-install: required app missing + caller opted in via commonParams.\n // Ask the user, install (DMK returns to dashboard then installs, streaming\n // AppInstallProgress ui-events), then retry the original op once. The\n // install runs as a direct connector call within THIS queue slot — going\n // through the public installApp/connectorCall would re-enter the serial\n // job queue and reject as busy.\n const autoInstallApp = commonParams?.autoInstallApp ?? this._defaultAutoInstallApp;\n const isAppMissing =\n isAppNotInstalledError(err) ||\n (err as { code?: number })?.code === HardwareErrorCode.AppNotInstalled;\n if (autoInstallApp && isAppMissing) {\n const appName = (err as { appName?: string })?.appName ?? mapLedgerError(err).appName;\n if (appName) {\n const confirmed = await this._waitForInstallAppConfirm(appName);\n if (!confirmed) throw err;\n // Emit progress 0 immediately so the confirm dialog morphs into the\n // \"installing\" view with no blank gap — DMK's setup (go-to-dashboard,\n // metadata, build plan, secure channel) can take several seconds\n // before the first real progress arrives.\n this.emitter.emit('ui-event', {\n type: EConnectorInteraction.AppInstallProgress,\n payload: { connectId: resolvedConnectId, appName, progress: 0 },\n });\n await this._callConnector(sessionId, 'installApp', { appName }, signal);\n // Close the install UI before retrying so the retried operation's own\n // device prompts (e.g. confirm-on-device) render normally instead of\n // being absorbed by the install dialog.\n this.emitter.emit(UI_REQUEST.CLOSE_UI_WINDOW, {\n type: UI_REQUEST.CLOSE_UI_WINDOW,\n payload: {},\n });\n return await this._callConnector(sessionId, method, effectiveParams, signal);\n }\n }\n\n // Stuck DMK slot — reset transport, wait briefly, retry ONCE.\n // Trigger: Stax CloseApp→OpenApp race returns APDU 6901 before the\n // user can react. A short pause lets the device finish its transition;\n // on persistent 6901 the user really does need to act, so surface it.\n if (isStuckAppStateError(err)) {\n try {\n this._sessions.delete(resolvedConnectId);\n this._discoveredDevices.delete(resolvedConnectId);\n this.connector.reset?.();\n } catch {\n // best-effort reset — fall through to retry\n }\n debugLog(\n '[LedgerAdapter] stuck-app retry: method=',\n method,\n 'delayMs=',\n LedgerAdapter.STUCK_APP_RETRY_DELAY_MS,\n '_tag=',\n (err as Record<string, unknown> | null | undefined)?._tag\n );\n try {\n const retryResult = await this._retryAfterStuckApp(\n resolvedConnectId,\n method,\n effectiveParams,\n signal,\n err,\n fingerprint\n );\n debugLog('[LedgerAdapter] stuck-app retry succeeded: method=', method);\n return retryResult;\n } catch (retryErr) {\n if (signal.aborted) throw retryErr;\n // Second stuck-app hit → genuinely needs user action; surface\n // the original error so callers see a consistent _tag.\n if (isStuckAppStateError(retryErr)) {\n debugLog('[LedgerAdapter] stuck-app retry exhausted (2nd 6901): method=', method);\n throw err;\n }\n debugLog(\n '[LedgerAdapter] stuck-app retry threw non-stuck error: method=',\n method,\n 'retryErrTag=',\n (retryErr as Record<string, unknown> | null | undefined)?._tag\n );\n throw retryErr;\n }\n }\n\n // Connection-class error → Layer 2 retry (bounded budget).\n // PairingFailure intentionally NOT retried — user declined the OS\n // pair prompt / didn't confirm on device, retrying makes no sense.\n if (\n isDeviceLockedError(err) ||\n isDeviceNotAdvertisingError(err) ||\n isDeviceDisconnectedError(err)\n ) {\n let lastErr: unknown = err;\n for (let attempt = 0; attempt < LedgerAdapter.MAX_BUSINESS_RETRY_BUDGET; attempt += 1) {\n if (signal.aborted) throw lastErr;\n\n try {\n this._sessions.delete(resolvedConnectId);\n this._discoveredDevices.delete(resolvedConnectId);\n\n // Disconnected: DMK transport may retain stale session. Drop\n // DMK so ensureConnected rebuilds from scratch. Locked /\n // NotAdvertising don't need this — DMK side is clean.\n if (isDeviceDisconnectedError(lastErr)) {\n try {\n this.connector.reset?.();\n } catch {\n // best-effort\n }\n }\n // ensureConnected → _doConnect handles \"device not found\" UI\n // request (search returns 0). DMK's unlock-device propagates\n // as a ui-event toast and self-recovers, so DeviceLocked from\n // DMK never reaches Layer 2. The only DeviceLocked here is\n // from APDU 0x5515 (rare hardware-direct), and _doConnect's\n // dialog still covers it via the same UI request.\n\n // Preserve connectId across retry to prevent multi-device drift.\n // USB replug fallback is allowed only when this call will verify\n // the device fingerprint before sending the business APDU.\n const reConnectId = await this.ensureConnected(\n resolvedConnectId,\n signal,\n allowUsbEphemeralFallback\n );\n const reSessionId = this._sessions.get(reConnectId);\n if (!reSessionId) throw lastErr;\n\n // Re-verify fingerprint — Layer 1 may have picked a different\n // physical device (multi-Ledger rig).\n if (fingerprint && !fingerprint.skipFingerprint && fingerprint.deviceId) {\n const fp = await this._abortable(\n signal,\n this._verifyDeviceFingerprintWithSession(\n reSessionId,\n fingerprint.deviceId,\n fingerprint.chain\n )\n );\n if (!fp.success) {\n throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {\n code: HardwareErrorCode.DeviceMismatch,\n });\n }\n }\n\n return await this._callConnector(reSessionId, method, effectiveParams, signal);\n } catch (retryErr) {\n if (signal.aborted) throw retryErr;\n lastErr = retryErr;\n const canRetry =\n attempt < LedgerAdapter.MAX_BUSINESS_RETRY_BUDGET - 1 &&\n (isDeviceLockedError(retryErr) ||\n isDeviceNotAdvertisingError(retryErr) ||\n isDeviceDisconnectedError(retryErr));\n if (!canRetry) {\n throw retryErr;\n }\n }\n }\n // Budget exhausted — surface last seen error to caller.\n throw lastErr;\n }\n\n if (isTimeoutError(err)) {\n debugLog('[LedgerAdapter] timeout, retrying with fresh connection...');\n this._discoveredDevices.delete(resolvedConnectId);\n return this._retryWithFreshConnection(\n resolvedConnectId,\n method,\n effectiveParams,\n signal,\n err,\n fingerprint\n );\n }\n\n // Fail-closed for connection-level errors so batch can't continue on\n // a wedged transport. Reset connector so next caller gets fresh DMK.\n if (isConnectionLevelError(err)) {\n debugLog('[LedgerAdapter] connection-level fail-closed reset');\n this._sessions.delete(resolvedConnectId);\n this._discoveredDevices.delete(resolvedConnectId);\n this.connector.reset();\n const codeNum = (err as { code?: number })?.code;\n throw Object.assign(err as Error, {\n code: codeNum ?? HardwareErrorCode.DeviceDisconnected,\n });\n }\n\n // Business errors (BlindSigning, AppStuck, etc.) propagate untouched.\n throw err;\n }\n }\n\n /**\n * Stuck-app recovery: pause for the device's UI transition, then retry once.\n *\n * Caller has already cleared the session + reset connector. We wait so Stax\n * finishes its post-CloseApp animation, then go through ensureConnected +\n * fingerprint check + call exactly once. Caller decides what to do on a\n * second stuck-app hit.\n */\n private async _retryAfterStuckApp(\n resolvedConnectId: string,\n method: string,\n params: unknown,\n signal: AbortSignal,\n originalErr: unknown,\n fingerprint?: ConnectorCallFingerprint\n ): Promise<unknown> {\n await this._sleepAbortable(LedgerAdapter.STUCK_APP_RETRY_DELAY_MS, signal);\n\n // Preserve connectId across retry (APDU 6901 didn't disconnect, so it's\n // still valid). If a USB replug changed the connectId, recover only when\n // the call has a fingerprint check queued immediately after reconnect.\n const retryConnectId = await this.ensureConnected(\n resolvedConnectId,\n signal,\n !!fingerprint?.deviceId && !fingerprint.skipFingerprint\n );\n const retrySessionId = this._sessions.get(retryConnectId);\n if (!retrySessionId) throw originalErr;\n\n if (fingerprint && !fingerprint.skipFingerprint && fingerprint.deviceId) {\n const fp = await this._abortable(\n signal,\n this._verifyDeviceFingerprintWithSession(\n retrySessionId,\n fingerprint.deviceId,\n fingerprint.chain\n )\n );\n if (!fp.success) {\n throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {\n code: HardwareErrorCode.DeviceMismatch,\n });\n }\n }\n\n return this._callConnector(retrySessionId, method, params, signal);\n }\n\n private _sleepAbortable(ms: number, signal: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal.aborted) {\n reject((signal.reason as Error | undefined) ?? new Error('Aborted'));\n return;\n }\n const timer = setTimeout(() => {\n signal.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n const onAbort = () => {\n clearTimeout(timer);\n reject((signal.reason as Error | undefined) ?? new Error('Aborted'));\n };\n signal.addEventListener('abort', onAbort, { once: true });\n });\n }\n\n /**\n * Clear stale session, reconnect, and retry the call.\n *\n * Timeout recovery starts with a full connector reset. After an APDU\n * timeout, DMK/transport state may still emit malformed responses; retrying\n * on the same DMK can poison the next chain switch.\n */\n private async _retryWithFreshConnection(\n targetConnectId: string,\n method: string,\n params: unknown,\n signal: AbortSignal,\n originalErr: unknown,\n fingerprint?: ConnectorCallFingerprint\n ): Promise<unknown> {\n this.connector.reset();\n this._sessions.clear();\n this._discoveredDevices.clear();\n this._connectingPromise = null;\n\n const allowUsbEphemeralFallback = !!fingerprint?.deviceId && !fingerprint.skipFingerprint;\n const retryConnectId = await this.ensureConnected(\n targetConnectId,\n signal,\n allowUsbEphemeralFallback\n );\n const retrySessionId = this._sessions.get(retryConnectId);\n if (!retrySessionId) {\n throw originalErr;\n }\n try {\n if (fingerprint && !fingerprint.skipFingerprint && fingerprint.deviceId) {\n const fp = await this._abortable(\n signal,\n this._verifyDeviceFingerprintWithSession(\n retrySessionId,\n fingerprint.deviceId,\n fingerprint.chain\n )\n );\n if (!fp.success) {\n throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {\n code: HardwareErrorCode.DeviceMismatch,\n });\n }\n }\n\n return await this._callConnector(retrySessionId, method, params, signal);\n } catch (retryErr) {\n if (signal.aborted) throw retryErr;\n this.connector.reset();\n this._sessions.clear();\n this._discoveredDevices.clear();\n this._connectingPromise = null;\n if (!isDeviceDisconnectedError(retryErr) && !isTimeoutError(retryErr)) {\n throw retryErr;\n }\n debugLog(\n '[LedgerAdapter] fresh-session retry still failed; resetting connector and rebuilding DMK'\n );\n // Full reset: drops _dmk, _deviceManager, _signerManager, ID maps\n // and in-flight cancellers. Next ensureConnected() will rebuild from\n // the ground up via _doConnect → connector.connect → fresh DMK.\n this.connector.reset();\n this._sessions.clear();\n this._discoveredDevices.clear();\n this._connectingPromise = null;\n const finalConnectId = await this.ensureConnected(\n targetConnectId,\n signal,\n allowUsbEphemeralFallback\n );\n const finalSessionId = this._sessions.get(finalConnectId);\n if (!finalSessionId) {\n throw originalErr;\n }\n\n // Re-verify fingerprint after the full reset — `ensureConnected` may have\n // selected a different physical device (e.g. multi-Ledger BLE rig where\n // the original peripheral went out of range). Without this replay,\n // `connector.call` could sign on the wrong device.\n if (fingerprint && !fingerprint.skipFingerprint && fingerprint.deviceId) {\n const fp = await this._abortable(\n signal,\n this._verifyDeviceFingerprintWithSession(\n finalSessionId,\n fingerprint.deviceId,\n fingerprint.chain\n )\n );\n if (!fp.success) {\n throw Object.assign(new Error(formatDeviceMismatchError(fp.expected, fp.actual)), {\n code: HardwareErrorCode.DeviceMismatch,\n });\n }\n }\n\n return this._callConnector(finalSessionId, method, params, signal);\n }\n }\n\n /**\n * Ensure OS-level device permission (Bluetooth / USB) before proceeding.\n *\n * Emits `REQUEST_DEVICE_PERMISSION` and awaits the consumer's\n * `RECEIVE_DEVICE_PERMISSION` reply (60s budget covers \"probe → system\n * prompt → user tap\" plus a generous margin). If the consumer never wires\n * a handler or never replies, the wait times out and the operation fails\n * fast so scanners/callers don't hang silently.\n *\n * - No connectId (searchDevices): environment-level permission\n * - With connectId (business methods): device-level permission\n */\n private async _ensureDevicePermission(\n connectId?: string,\n deviceId?: string,\n signal?: AbortSignal\n ): Promise<void> {\n if (signal?.aborted) {\n LedgerAdapter._throwIfAborted(signal);\n }\n const transportType: TransportType = this.activeTransport ?? 'hid';\n\n // Register the wait before emitting — a synchronous listener that replies\n // immediately (e.g. in tests or a same-process consumer) would otherwise\n // resolve before any pending entry exists and the response would drop.\n const waitPromise = this._uiRegistry.wait<DevicePermissionResponse>(\n UI_REQUEST.REQUEST_DEVICE_PERMISSION,\n { timeoutMs: 60_000 }\n );\n\n this.emitter.emit(UI_REQUEST.REQUEST_DEVICE_PERMISSION, {\n type: UI_REQUEST.REQUEST_DEVICE_PERMISSION,\n payload: { transportType, connectId, deviceId },\n });\n\n let response: DevicePermissionResponse;\n const onAbort = () => {\n this._uiRegistry.cancel(UI_REQUEST.REQUEST_DEVICE_PERMISSION);\n };\n try {\n signal?.addEventListener('abort', onAbort, { once: true });\n response = await waitPromise;\n } catch (err) {\n if (signal?.aborted) {\n LedgerAdapter._throwIfAborted(signal);\n }\n // Defensive: same-type re-fire of REQUEST_DEVICE_PERMISSION could\n // preempt this wait. Surface as UserAborted so upstream classifiers\n // stop the batch cleanly instead of bubbling an unmapped tag.\n if ((err as { _tag?: string })?._tag === UI_REQUEST_PREEMPTED_TAG) {\n this.emitter.emit(UI_REQUEST.CLOSE_UI_WINDOW, {\n type: UI_REQUEST.CLOSE_UI_WINDOW,\n payload: {},\n });\n throw Object.assign(new Error('Device permission request superseded'), {\n _tag: ERROR_TAG.UserAborted,\n code: HardwareErrorCode.UserAborted,\n cause: err,\n });\n }\n throw err;\n } finally {\n signal?.removeEventListener('abort', onAbort);\n }\n\n const { granted, reason, message } = response;\n\n if (!granted) {\n throw Object.assign(new Error(message ?? 'Device permission denied'), {\n code: HardwareErrorCode.DevicePermissionDenied,\n reason,\n });\n }\n }\n\n /**\n * Convert a thrown error to a Response failure.\n * Uses mapLedgerError to parse Ledger DMK error codes into HardwareErrorCode values.\n */\n private errorToFailure<T>(err: unknown): Response<T> {\n debugError('[LedgerAdapter] error:', err);\n\n // Preserve `_tag` so SDK classifiers survive the Failure round-trip.\n const tag = err && typeof err === 'object' ? (err as { _tag?: string })._tag : undefined;\n\n // If the error carries an explicit HardwareErrorCode (e.g. validation errors\n // thrown by connector chain methods), use it directly.\n if (\n err &&\n typeof err === 'object' &&\n 'code' in err &&\n typeof (err as { code: unknown }).code === 'number'\n ) {\n const e = err as {\n code: number;\n message?: string;\n appName?: string;\n reason?: string;\n params?: Record<string, unknown>;\n };\n const params =\n e.code === HardwareErrorCode.DevicePermissionDenied && e.reason\n ? { permissionDeniedReason: e.reason }\n : e.params;\n return ledgerFailure(e.code, e.message ?? 'Unknown error', e.appName, tag, params);\n }\n\n const mapped = mapLedgerError(err);\n\n // DeviceLocked is handled by connectorCall retry logic (_waitForDeviceConnect).\n // Do NOT emit UI events here — it would show UI and return error simultaneously.\n\n return ledgerFailure(mapped.code, mapped.message, mapped.appName, tag);\n }\n\n // ---------------------------------------------------------------------------\n // Event translation\n // ---------------------------------------------------------------------------\n\n private deviceConnectHandler = (data: { device: ConnectorDevice }): void => {\n const deviceInfo = this.connectorDeviceToDeviceInfo(data.device);\n this._discoveredDevices.set(deviceInfo.connectId, deviceInfo);\n // Clear any stale session for this connectId so ensureConnected() does a fresh connect.\n // This handles the case where the connector reconnected internally (e.g. TRON app switch).\n this._sessions.delete(deviceInfo.connectId);\n this.emitter.emit(DEVICE.CONNECT, {\n type: DEVICE.CONNECT,\n payload: deviceInfo,\n });\n };\n\n private deviceDisconnectHandler = (data: { connectId: string }): void => {\n this._discoveredDevices.delete(data.connectId);\n this._sessions.delete(data.connectId);\n this.emitter.emit(DEVICE.DISCONNECT, {\n type: DEVICE.DISCONNECT,\n payload: { connectId: data.connectId },\n });\n };\n\n // Forward connector `ui-event` to the public hw.emitter so consumers only\n // need to subscribe in one place. For the AppInstallProgress variant we\n // re-key sessionId → connectId via the live _sessions map; if no mapping\n // exists (race during teardown) we drop. All other variants pass through\n // unchanged.\n private uiEventForwarder = (event: ConnectorUiEvent): void => {\n if (event.type === EConnectorInteraction.AppInstallProgress) {\n let connectId: string | undefined;\n for (const [cid, sid] of this._sessions) {\n if (sid === event.payload.sessionId) {\n connectId = cid;\n break;\n }\n }\n if (!connectId) {\n debugLog(\n '[LedgerAdapter] dropping AppInstallProgress: no connectId for sessionId',\n event.payload.sessionId\n );\n return;\n }\n this.emitter.emit('ui-event', {\n type: EConnectorInteraction.AppInstallProgress,\n payload: {\n connectId,\n appName: event.payload.appName,\n progress: event.payload.progress,\n },\n });\n return;\n }\n this.emitter.emit('ui-event', event);\n };\n\n private registerEventListeners(): void {\n this.connector.on('device-connect', this.deviceConnectHandler);\n this.connector.on('device-disconnect', this.deviceDisconnectHandler);\n this.connector.on('ui-event', this.uiEventForwarder);\n }\n\n private unregisterEventListeners(): void {\n this.connector.off('device-connect', this.deviceConnectHandler);\n this.connector.off('device-disconnect', this.deviceDisconnectHandler);\n this.connector.off('ui-event', this.uiEventForwarder);\n }\n\n // ---------------------------------------------------------------------------\n // Device info mapping\n // ---------------------------------------------------------------------------\n\n private connectorDeviceToDeviceInfo(device: ConnectorDevice): DeviceInfo {\n return {\n vendor: 'ledger',\n model: device.model ?? 'unknown',\n modelName: device.modelName,\n firmwareVersion: '',\n deviceId: device.deviceId,\n connectId: device.connectId,\n label: device.name,\n connectionType: this.connector.connectionType,\n rssi: device.rssi,\n isConnectable: device.isConnectable,\n serialNumber: device.serialNumber,\n capabilities: device.capabilities,\n };\n }\n}\n","import { HardwareErrorCode, enrichErrorMessage } from '@onekeyfe/hwk-adapter-core';\n\nimport type { Failure } from '@onekeyfe/hwk-adapter-core';\n\nexport const MULTIPLE_USB_LEDGER_DEVICES_ERROR_MESSAGE =\n 'Multiple Ledger USB devices are connected. Please connect only one Ledger device and try again.';\n\nexport function createMultipleUsbLedgerDevicesError(): Error & { code: HardwareErrorCode } {\n return Object.assign(new Error(MULTIPLE_USB_LEDGER_DEVICES_ERROR_MESSAGE), {\n code: HardwareErrorCode.DeviceOneDeviceOnly,\n });\n}\n\n// `_tag` survives errorToFailure → re-throw so SDK classifiers keep working.\nexport type LedgerFailure = Omit<Failure, 'payload'> & {\n payload: Failure['payload'] & { appName?: string; _tag?: string };\n};\n\nexport interface WrapErrorOptions {\n /** Fallback when err has no `appName` (DMK signer errors don't carry it). */\n defaultAppName?: string;\n}\n\nexport function ledgerFailure(\n code: HardwareErrorCode,\n error: string,\n appName?: string,\n tag?: string,\n params?: Record<string, unknown>\n): LedgerFailure {\n const payload: LedgerFailure['payload'] = { error, code };\n if (appName !== undefined) payload.appName = appName;\n if (tag !== undefined) payload._tag = tag;\n if (params !== undefined) payload.params = params;\n return { success: false, payload };\n}\n\n/**\n * DMK locked device status codes:\n * 0x5515 (21781) — primary locked response\n * 0x6982 (27010) — security status not satisfied\n * 0x5303 (21251) — tertiary locked response\n */\nconst LOCKED_ERROR_CODES = new Set(['5515', '21781', '6982', '27010', '5303', '21251']);\n\n/**\n * DMK user-rejected status codes:\n * 0x6985 (27013) — conditions of use not satisfied (user denied on device)\n */\nconst USER_REJECTED_CODES = new Set(['6985', '27013']);\n\n/**\n * DMK wrong-app / CLA-not-supported status codes:\n * 0x6e00 (28160) — CLA not supported (wrong app open)\n * 0x6d00 (27904) — INS not supported (wrong app or outdated app)\n * 0x6a83 (27267) — Referenced data not found (wrong app for raw APDU, e.g. TRON)\n */\nconst WRONG_APP_CODES = new Set(['6e00', '28160', '6d00', '27904', '6a83', '27267']);\n\n/**\n * DMK app-not-installed status codes:\n * 0x6807 (26631) — Unknown application name (app not installed on device)\n */\nconst APP_NOT_INSTALLED_CODES = new Set(['6807', '26631']);\n\n/**\n * DMK step value emitted when SignTransactionDeviceAction retries with\n * basic/blind signing. Used to distinguish APDU 0x6a80 (\"Invalid data\")\n * caused by a blind-sign fallback from a generic malformed transaction.\n */\nconst STEP_BLIND_SIGN_TRANSACTION_FALLBACK = 'signer.eth.steps.blindSignTransactionFallback';\n\n/**\n * Read the Ledger Ethereum App APDU error code from a DMK error object.\n * Returns the code in lowercase (e.g. \"6a80\") or `null` if not present.\n */\nfunction getEthAppErrorCode(err: unknown): string | null {\n if (!err || typeof err !== 'object') return null;\n const e = err as Record<string, unknown>;\n if (e._tag === ERROR_TAG.EthAppCommand && typeof e.errorCode === 'string') {\n return e.errorCode.toLowerCase();\n }\n const orig = e.originalError as Record<string, unknown> | undefined;\n if (orig?._tag === ERROR_TAG.EthAppCommand && typeof orig.errorCode === 'string') {\n return orig.errorCode.toLowerCase();\n }\n return null;\n}\n\n/**\n * Extract an APDU status word in lowercase hex. Handles DMK's hex-string\n * `errorCode`, legacy TransportStatusError's numeric `statusCode`, and\n * recurses through `originalError` for wrapped errors.\n */\nfunction extractApduHex(err: unknown): string | null {\n if (!err || typeof err !== 'object') return null;\n const e = err as Record<string, unknown>;\n if (typeof e.errorCode === 'string' && /^[0-9a-f]+$/i.test(e.errorCode)) {\n return e.errorCode.toLowerCase();\n }\n if (typeof e.statusCode === 'number' && Number.isFinite(e.statusCode)) {\n return e.statusCode.toString(16).padStart(4, '0');\n }\n if (typeof e.statusCode === 'string' && /^[0-9a-f]+$/i.test(e.statusCode)) {\n return e.statusCode.toLowerCase();\n }\n if (e.originalError != null) {\n const nested = extractApduHex(e.originalError);\n if (nested) return nested;\n }\n if (e.error != null && typeof e._tag === 'string') {\n const nested = extractApduHex(e.error);\n if (nested) return nested;\n }\n return null;\n}\n\n/** Solana APDU → code. 0x6808 arrives as a plain DeviceExchangeError,\n * not wrapped in SolanaAppCommandError, so match by code only. */\nfunction mapSolanaAppError(hex: string): HardwareErrorCode | null {\n switch (hex) {\n case '6808':\n return HardwareErrorCode.SolanaBlindSigningRequired;\n default:\n return null;\n }\n}\n\n/** Tron APDU → code. Source: app-tron/src/app_errors.h (E_MISSING_SETTING_*). */\nfunction mapTronAppError(hex: string): HardwareErrorCode | null {\n switch (hex) {\n case '6a8d':\n return HardwareErrorCode.TronCustomContractRequired;\n case '6a8b':\n return HardwareErrorCode.TronDataSigningRequired;\n case '6a8c':\n return HardwareErrorCode.TronSignByHashRequired;\n default:\n return null;\n }\n}\n\n/** BTC APDU → code. 0xb000 range is disjoint from other apps' 0x6xxx. */\nfunction mapBtcAppError(hex: string): HardwareErrorCode | null {\n switch (hex) {\n case 'b008':\n return HardwareErrorCode.BtcWalletPolicyHmacMismatch;\n case 'b007':\n return HardwareErrorCode.BtcUnexpectedState;\n default:\n return null;\n }\n}\n\n/**\n * Map unambiguous Ledger Ethereum App APDU status words to HardwareErrorCode.\n * Ambiguous status words, such as 0x6a80, are classified with full error\n * context in `classifyEthAppError`.\n */\nfunction mapEthAppErrorCode(ethCode: string): HardwareErrorCode | null {\n switch (ethCode) {\n case '6984':\n return HardwareErrorCode.EvmClearSignPluginMissing;\n case '6a84':\n return HardwareErrorCode.EvmDataTooLarge;\n case '6501':\n return HardwareErrorCode.EvmTxTypeNotSupported;\n case '911c':\n return HardwareErrorCode.AppTooOld;\n default:\n return null;\n }\n}\n\nfunction classifyEthAppError(err: unknown): HardwareErrorCode | null {\n const ethCode = getEthAppErrorCode(err);\n if (!ethCode) return null;\n\n // 0x6a80 is a broad \"Invalid data\" APDU. Only report blind-signing\n // guidance when DMK actually entered the blind-sign fallback branch.\n if (ethCode === '6a80') {\n return hasBlindSignFallbackStep(err) ? HardwareErrorCode.EvmBlindSigningRequired : null;\n }\n\n return mapEthAppErrorCode(ethCode);\n}\n\n// Centralized `_tag` constants — single source of truth for both writes and\n// classifier comparisons. Typos fail at compile time.\nexport const ERROR_TAG = {\n // SDK-mint\n DeviceNotAdvertising: 'DeviceNotAdvertisingError', // BLE scan miss\n DeviceNotInDiscoveryCache: 'DeviceNotInDiscoveryCacheError', // dm.connect() before enumerate\n BlePairingTimeout: 'BlePairingTimeoutError', // SMP 30s timeout\n BleGattBondingFailed: 'BleGattBondingFailedError', // other GATT failure\n UserAborted: 'UserAborted',\n DeviceAppStuck: 'DeviceAppStuck', // chain app wedged (APDU 0x6901)\n DeviceTransportStuck: 'DeviceTransportStuck', // DMK transport queue wedged\n\n // DMK-reuse (DMK throws same string; we synthesize too)\n DeviceLocked: 'DeviceLockedError',\n DeviceNotRecognized: 'DeviceNotRecognizedError',\n DeviceSessionNotFound: 'DeviceSessionNotFound',\n OpenAppCommand: 'OpenAppCommandError',\n\n // DMK-only (read only)\n EthAppCommand: 'EthAppCommandError',\n UserRefusedOnDevice: 'UserRefusedOnDevice',\n WrongAppOpened: 'WrongAppOpenedError',\n InvalidStatusWord: 'InvalidStatusWordError',\n AlreadySendingApdu: 'AlreadySendingApduError',\n UnknownDeviceExchange: 'UnknownDeviceExchangeError',\n NoAccessibleDevice: 'NoAccessibleDeviceError',\n UnknownDevice: 'UnknownDeviceError',\n DeviceSessionRefresher: 'DeviceSessionRefresherError',\n DeviceNotInitialized: 'DeviceNotInitializedError',\n OpeningConnection: 'OpeningConnectionError',\n DeviceDisconnectedBeforeSendingApdu: 'DeviceDisconnectedBeforeSendingApdu',\n DeviceDisconnectedWhileSending: 'DeviceDisconnectedWhileSendingError',\n Disconnect: 'DisconnectError',\n ReconnectionFailed: 'ReconnectionFailedError',\n WebHIDDisconnect: 'WebHIDDisconnectError',\n // ble-plx surfaces this when GATT notification setup fails — typical\n // outcome when the user doesn't confirm pairing on the device, or the\n // existing bond is invalid. Observed in production after ~30s.\n PairingRefused: 'PairingRefusedError',\n} as const;\n\nexport type SdkErrorTag = (typeof ERROR_TAG)[keyof typeof ERROR_TAG];\n\n// Strict: only SE-locked. DeviceNotAdvertising / BlePairingTimeout etc are\n// their own classifiers — don't conflate.\nexport function isDeviceLockedError(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false;\n const e = err as Record<string, unknown>;\n if (e.errorCode != null && LOCKED_ERROR_CODES.has(String(e.errorCode))) return true;\n if (e.statusCode != null && LOCKED_ERROR_CODES.has(String(e.statusCode))) return true;\n if (e._tag === ERROR_TAG.DeviceLocked) return true;\n if (e.originalError != null && isDeviceLockedError(e.originalError)) return true;\n if (e.error != null && e._tag && isDeviceLockedError(e.error)) return true;\n return false;\n}\n\n// BLE scan miss — peripheral not seen, recoverable via unlock prompt.\nexport function isDeviceNotAdvertisingError(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false;\n return (err as { _tag?: string })._tag === ERROR_TAG.DeviceNotAdvertising;\n}\n\n// GATT bonding failed (non-timeout). Not auto-retryable.\nexport function isBleGattBondingFailedError(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false;\n return (err as { _tag?: string })._tag === ERROR_TAG.BleGattBondingFailed;\n}\n\n// Any BLE pairing failure (DMK-native, ble-plx, our own). All map to\n// `code: BlePairingTimeout` so batch fail-closes uniformly. User-cancel of\n// the system pairing dialog also lands here — to the user it's the same\n// \"didn't pair\" outcome, no need to disambiguate.\nconst PAIRING_FAILURE_TAGS = new Set<string>([\n ERROR_TAG.BlePairingTimeout,\n ERROR_TAG.BleGattBondingFailed,\n ERROR_TAG.PairingRefused,\n]);\nexport function isBlePairingFailureError(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false;\n const tag = (err as { _tag?: string })._tag;\n if (tag && PAIRING_FAILURE_TAGS.has(tag)) return true;\n const orig = (err as { originalError?: unknown }).originalError;\n if (orig != null && isBlePairingFailureError(orig)) return true;\n return false;\n}\n\n// \"Connection is broken\" — next call can't reuse the session. Used by\n// Layer 2 fail-closed gate.\nconst CONNECTION_LEVEL_TAGS: Set<string> = new Set([\n ERROR_TAG.DeviceLocked,\n ERROR_TAG.DeviceNotAdvertising,\n ERROR_TAG.BlePairingTimeout,\n ERROR_TAG.BleGattBondingFailed,\n ERROR_TAG.PairingRefused,\n ERROR_TAG.DeviceNotRecognized,\n ERROR_TAG.NoAccessibleDevice,\n ERROR_TAG.UnknownDevice,\n ERROR_TAG.DeviceSessionNotFound,\n ERROR_TAG.DeviceSessionRefresher,\n ERROR_TAG.DeviceNotInitialized,\n ERROR_TAG.OpeningConnection,\n ERROR_TAG.DeviceDisconnectedBeforeSendingApdu,\n ERROR_TAG.DeviceDisconnectedWhileSending,\n ERROR_TAG.Disconnect,\n ERROR_TAG.ReconnectionFailed,\n ERROR_TAG.WebHIDDisconnect,\n]);\n\nconst DEVICE_NOT_FOUND_TAGS: Set<string> = new Set([\n ERROR_TAG.NoAccessibleDevice,\n ERROR_TAG.UnknownDevice,\n ERROR_TAG.DeviceNotInitialized,\n // SDK-internal: dm.connect() called before _discovered was populated.\n // Map to DeviceNotFound so non-BLE-direct paths get a sensible error code.\n ERROR_TAG.DeviceNotInDiscoveryCache,\n]);\n\nconst DEVICE_BUSY_TAGS: Set<string> = new Set([ERROR_TAG.OpeningConnection]);\n\nconst DEVICE_DISCONNECTED_TAGS: Set<string> = new Set([\n ERROR_TAG.DeviceNotRecognized,\n ERROR_TAG.DeviceSessionNotFound,\n ERROR_TAG.DeviceSessionRefresher,\n ERROR_TAG.DeviceDisconnectedBeforeSendingApdu,\n ERROR_TAG.DeviceDisconnectedWhileSending,\n ERROR_TAG.Disconnect,\n ERROR_TAG.ReconnectionFailed,\n ERROR_TAG.WebHIDDisconnect,\n]);\n\nexport function isConnectionLevelError(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false;\n const tag = (err as { _tag?: string })._tag;\n if (tag && CONNECTION_LEVEL_TAGS.has(tag)) return true;\n // Recurse into nested DMK error envelopes (originalError / error.{_tag})\n const e = err as Record<string, unknown>;\n if (e.originalError != null && isConnectionLevelError(e.originalError)) return true;\n if (e.error != null && e._tag && isConnectionLevelError(e.error)) return true;\n return false;\n}\n\n/** Expose for connector — used to decide whether to pass an error through\n * unchanged or wrap as BleGattBondingFailed. */\nexport function isKnownConnectionTag(tag: unknown): boolean {\n return typeof tag === 'string' && CONNECTION_LEVEL_TAGS.has(tag);\n}\n\n/** Check if a status/error code exists in the given set, crawling the error chain. */\nfunction hasStatusCode(err: unknown, codeSet: Set<string>): boolean {\n if (!err || typeof err !== 'object') return false;\n const e = err as Record<string, unknown>;\n if (e.errorCode != null && codeSet.has(String(e.errorCode))) return true;\n if (e.statusCode != null && codeSet.has(String(e.statusCode))) return true;\n if (e.originalError != null && hasStatusCode(e.originalError, codeSet)) return true;\n if (e.error != null && e._tag && hasStatusCode(e.error, codeSet)) return true;\n return false;\n}\n\nfunction hasBlindSignFallbackStep(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false;\n const e = err as Record<string, unknown>;\n\n if (e._lastStep === STEP_BLIND_SIGN_TRANSACTION_FALLBACK) return true;\n\n if (\n Array.isArray(e._deviceActionSteps) &&\n e._deviceActionSteps.includes(STEP_BLIND_SIGN_TRANSACTION_FALLBACK)\n ) {\n return true;\n }\n\n if (e.originalError != null && hasBlindSignFallbackStep(e.originalError)) return true;\n if (e.error != null && e._tag && hasBlindSignFallbackStep(e.error)) return true;\n return false;\n}\n\nfunction isDeviceNotFoundError(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false;\n const tag = (err as { _tag?: string })._tag;\n if (tag && DEVICE_NOT_FOUND_TAGS.has(tag)) return true;\n const e = err as Record<string, unknown>;\n if (e.originalError != null && isDeviceNotFoundError(e.originalError)) return true;\n if (e.error != null && e._tag && isDeviceNotFoundError(e.error)) return true;\n return false;\n}\n\nfunction isDeviceBusyError(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false;\n const tag = (err as { _tag?: string })._tag;\n if (tag && DEVICE_BUSY_TAGS.has(tag)) return true;\n const e = err as Record<string, unknown>;\n if (e.originalError != null && isDeviceBusyError(e.originalError)) return true;\n if (e.error != null && e._tag && isDeviceBusyError(e.error)) return true;\n return false;\n}\n\n/** Check for user rejection (denied on device). */\nexport function isUserRejectedError(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false;\n const e = err as Record<string, unknown>;\n if (e._tag === ERROR_TAG.UserRefusedOnDevice) return true;\n if (typeof e.message === 'string' && /denied|rejected|refused/i.test(e.message)) return true;\n if (hasStatusCode(err, USER_REJECTED_CODES)) return true;\n return false;\n}\n\n/** Check for wrong app open on the device. */\nexport function isWrongAppError(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false;\n const e = err as Record<string, unknown>;\n if (e._tag === ERROR_TAG.WrongAppOpened || e._tag === ERROR_TAG.InvalidStatusWord) {\n if (hasStatusCode(err, WRONG_APP_CODES)) return true;\n }\n if (typeof e.message === 'string') {\n const msg = e.message.toLowerCase();\n if (msg.includes('wrong app') || msg.includes('open the') || msg.includes('cla not supported'))\n return true;\n }\n if (hasStatusCode(err, WRONG_APP_CODES)) return true;\n return false;\n}\n\n/** Check for app not installed on device. */\nexport function isAppNotInstalledError(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false;\n const e = err as Record<string, unknown>;\n if (typeof e.message === 'string' && /unknown application/i.test(e.message)) return true;\n if (hasStatusCode(err, APP_NOT_INSTALLED_CODES)) return true;\n return false;\n}\n\n/** DMK install ran out of space on the device. Identified by the DMK error tag. */\nexport function isOutOfMemoryError(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false;\n const e = err as Record<string, unknown>;\n return e._tag === 'OutOfMemoryDAError';\n}\n\n/** Check for device disconnected errors. */\nexport function isDeviceDisconnectedError(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false;\n const e = err as Record<string, unknown>;\n const tag = e._tag;\n if (typeof tag === 'string' && DEVICE_DISCONNECTED_TAGS.has(tag)) return true;\n if (typeof e.message === 'string') {\n const msg = e.message.toLowerCase();\n if (\n msg.includes('disconnected') ||\n msg.includes('not found') ||\n msg.includes('no device') ||\n msg.includes('unplugged')\n )\n return true;\n }\n return false;\n}\n\n/**\n * DMK timeout error _tag values.\n * These are the concrete error classes from @ledgerhq/device-management-kit.\n */\nconst TIMEOUT_TAGS = new Set([\n 'DeviceExchangeTimeoutError',\n 'SendApduTimeoutError',\n 'SendCommandTimeoutError',\n]);\n\n/** Check for timeout errors using DMK's _tag identifiers or wrapped error code. */\nexport function isTimeoutError(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false;\n const e = err as Record<string, unknown>;\n if (typeof e._tag === 'string' && TIMEOUT_TAGS.has(e._tag)) return true;\n if (e.code === HardwareErrorCode.OperationTimeout) return true;\n return false;\n}\n\n/** Chain app wedged: APDU 0x6901 — only the user pressing both buttons recovers. */\nexport function isAppStuckByApdu(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false;\n const tag = (err as Record<string, unknown>)._tag;\n if (tag === ERROR_TAG.DeviceAppStuck) return true; // already wrapped form\n return extractApduHex(err) === '6901';\n}\n\n/** DMK transport / IntentQueue slot wedged — recover via connector.reset(). */\nexport function isTransportStuck(err: unknown): boolean {\n if (!err || typeof err !== 'object') return false;\n const tag = (err as Record<string, unknown>)._tag;\n return (\n tag === ERROR_TAG.DeviceTransportStuck || // already wrapped form\n tag === ERROR_TAG.UnknownDeviceExchange ||\n tag === ERROR_TAG.AlreadySendingApdu\n );\n}\n\n/** Union: any stuck state, regardless of root cause. Used by Layer 2 catch. */\nexport function isStuckAppStateError(err: unknown): boolean {\n return isAppStuckByApdu(err) || isTransportStuck(err);\n}\n\n/**\n * Map a Ledger DMK error to a HardwareErrorCode and human-readable message.\n * `opts.defaultAppName` fills `appName` when the raw error doesn't carry it\n * (DMK signer errors don't).\n */\nexport function mapLedgerError(\n err: unknown,\n opts?: WrapErrorOptions\n): {\n code: HardwareErrorCode;\n message: string;\n appName?: string;\n} {\n // Order matters: check more specific errors first\n\n // Extract the original message for fallback / enrichment\n let originalMessage = 'Unknown Ledger error';\n if (err instanceof Error) {\n originalMessage = err.message;\n } else if (err && typeof err === 'object') {\n const e = err as Record<string, unknown>;\n originalMessage = String(e.message ?? e._tag ?? e.type ?? JSON.stringify(err));\n }\n\n let code: HardwareErrorCode;\n\n // DeviceLocked: _tag handoff (unlock-device) or APDU 0x5515/0x6982.\n if (isDeviceLockedError(err)) {\n code = HardwareErrorCode.DeviceLocked;\n } else if (isDeviceNotAdvertisingError(err) || isDeviceNotFoundError(err)) {\n code = HardwareErrorCode.DeviceNotFound;\n } else if (isDeviceBusyError(err)) {\n code = HardwareErrorCode.DeviceBusy;\n } else if (isBlePairingFailureError(err)) {\n code = HardwareErrorCode.BlePairingTimeout;\n } else if (isUserRejectedError(err)) {\n // User rejection (0x6985) must win over EthAppError mapping — a user-cancelled\n // blind-sign is not a \"please enable Blind signing\" situation.\n code = HardwareErrorCode.UserRejected;\n } else if (isWrongAppError(err)) {\n code = HardwareErrorCode.WrongApp;\n } else if (isAppNotInstalledError(err)) {\n code = HardwareErrorCode.AppNotInstalled;\n } else if (isOutOfMemoryError(err)) {\n code = HardwareErrorCode.DeviceOutOfMemory;\n } else if (isDeviceDisconnectedError(err)) {\n code = HardwareErrorCode.DeviceDisconnected;\n } else if (isTimeoutError(err)) {\n code = HardwareErrorCode.OperationTimeout;\n } else {\n const ethMapped = classifyEthAppError(err);\n\n // Solana / Tron / BTC APDU codes — disjoint from EVM's table, single-pass lookup.\n const apduHex = ethMapped ? null : extractApduHex(err);\n const chainMapped = apduHex\n ? mapSolanaAppError(apduHex) ?? mapTronAppError(apduHex) ?? mapBtcAppError(apduHex)\n : null;\n\n code = ethMapped ?? chainMapped ?? HardwareErrorCode.UnknownError;\n }\n\n const errAppName =\n err && typeof err === 'object'\n ? ((err as Record<string, unknown>).appName as string | undefined)\n : undefined;\n const appName = errAppName ?? opts?.defaultAppName;\n\n return { code, message: enrichErrorMessage(code, originalMessage), appName };\n}\n","import type { ConnectionType, DeviceDescriptor } from '@onekeyfe/hwk-adapter-core';\n\n/**\n * Ledger DMK transport identifiers that represent BLE devices.\n *\n * Known today:\n * - \"BLE\": generic/web BLE descriptors\n * - \"RN_BLE\": @ledgerhq/device-transport-kit-react-native-ble\n *\n * Keep the suffix check here so future DMK BLE transports (for example\n * \"FOO_BLE\") are handled in one place instead of scattering string checks.\n */\nexport function isLedgerDmkBleTransport(transport?: string): boolean {\n const normalized = transport?.toUpperCase();\n return normalized === 'BLE' || normalized?.endsWith('_BLE') === true;\n}\n\nexport function isLedgerBleConnectionType(connectionType?: ConnectionType): boolean {\n return connectionType === 'ble';\n}\n\nexport function isLedgerBleDescriptor(\n connectionType: ConnectionType,\n descriptor: DeviceDescriptor\n): boolean {\n return isLedgerBleConnectionType(connectionType) || isLedgerDmkBleTransport(descriptor.transport);\n}\n","/**\n * SDK-global event bus. Per-runtime singleton — each process subscribes\n * independently; cross-process hosts forward events over their own IPC.\n */\n\nexport type SdkLogEvent = {\n type: 'log';\n level: 'debug' | 'error';\n /** Pre-stringified payload. */\n message: string;\n};\n\n/** Add new variants here; hosts dispatch on `event.type`. */\nexport type SdkEvent = SdkLogEvent;\n\nexport type SdkEventListener = (event: SdkEvent) => void;\n\nconst listeners = new Set<SdkEventListener>();\n\nexport function onSdkEvent(listener: SdkEventListener): () => void {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n}\n\nexport function offSdkEvent(listener: SdkEventListener): void {\n listeners.delete(listener);\n}\n\nexport function emitSdkEvent(event: SdkEvent): void {\n if (listeners.size === 0) return;\n for (const listener of listeners) {\n try {\n listener(event);\n } catch {\n // Misbehaving listeners must not take down the SDK.\n }\n }\n}\n\n/** Stringify args once and emit a log event. No-op when no subscribers. */\nexport function emitLog(level: 'debug' | 'error', ...args: unknown[]): void {\n if (listeners.size === 0) return;\n const message = args.map(a => (typeof a === 'string' ? a : safeStringify(a))).join(' ');\n emitSdkEvent({ type: 'log', level, message });\n}\n\nfunction safeStringify(value: unknown): string {\n if (value instanceof Error) {\n return value.stack ? `${value.message}\\n${value.stack}` : value.message;\n }\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n","/** SDK-internal log helpers. Emit through `sdkEventBus`; silent if nobody subscribes. */\nimport { emitLog } from './sdkEventBus';\n\nexport function debugLog(...args: unknown[]): void {\n emitLog('debug', ...args);\n}\n\nexport function debugError(...args: unknown[]): void {\n emitLog('error', ...args);\n}\n","import {\n EConnectorInteraction,\n HardwareErrorCode,\n serializeConnectorError,\n} from '@onekeyfe/hwk-adapter-core';\n\nimport { LedgerDeviceManager } from '../device/LedgerDeviceManager';\nimport { SignerManager } from '../signer/SignerManager';\nimport {\n ERROR_TAG,\n isAppStuckByApdu,\n isKnownConnectionTag,\n isTransportStuck,\n mapLedgerError,\n} from '../errors';\nimport { debugLog } from '../utils/debugLog';\nimport { isLedgerBleConnectionType } from '../utils/ledgerDmkTransport';\nimport {\n btcGetAddress,\n btcGetMasterFingerprint,\n btcGetPublicKey,\n btcSignMessage,\n btcSignPsbt,\n btcSignTransaction,\n evmGetAddress,\n evmSignMessage,\n evmSignTransaction,\n evmSignTypedData,\n solGetAddress,\n solSignMessage,\n solSignTransaction,\n tronGetAddress,\n tronSignMessage,\n tronSignTransaction,\n} from './chains';\nimport { DeviceAppsManager } from '../device-apps/DeviceAppsManager';\nimport { collapseSignerInteraction } from './chains/utils';\n\nimport type {\n DeviceApps,\n InstallAppCallParams,\n ListInstalledAppsCallParams,\n} from '../device-apps/DeviceApps';\nimport type { ConnectorContext } from './chains/types';\nimport type { WrapErrorOptions } from '../errors';\nimport type { CancelReason } from '../signer/deviceActionToPromise';\nimport type { DeviceManagementKit } from '@ledgerhq/device-management-kit';\nimport type {\n ConnectionType,\n ConnectorCallResult,\n ConnectorDevice,\n ConnectorEventMap,\n ConnectorEventType,\n ConnectorSession,\n DeviceDescriptor,\n IConnector,\n TronSignMsgParams,\n UiResponseEvent,\n} from '@onekeyfe/hwk-adapter-core';\nimport type {\n BtcGetAddressCallParams,\n BtcGetPublicKeyCallParams,\n BtcSignMessageCallParams,\n BtcSignPsbtCallParams,\n BtcSignTransactionCallParams,\n EvmGetAddressCallParams,\n EvmSignMessageCallParams,\n EvmSignTransactionCallParams,\n EvmSignTypedDataCallParams,\n SolGetAddressCallParams,\n SolSignMessageCallParams,\n SolSignTransactionCallParams,\n TronGetAddressCallParams,\n TronSignMessageCallParams,\n TronSignTransactionCallParams,\n} from './chains';\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\n/**\n * A function that lazily loads and returns the transport factory\n * for the Ledger DMK builder (e.g. webHidTransportFactory, rnBleTransportFactory).\n */\nexport type TransportFactory = () => Promise<unknown>;\n\nexport interface LedgerConnectorBaseOptions {\n /**\n * Pre-built DMK instance. If not provided, a DMK will be created\n * lazily on first use via the transport factory.\n */\n dmk?: DeviceManagementKit;\n}\n\n// ---------------------------------------------------------------------------\n// Internal types\n// ---------------------------------------------------------------------------\n\ntype EventHandler<K extends ConnectorEventType> = (data: ConnectorEventMap[K]) => void;\n\n/**\n * Method-name prefix → Ledger app name. Keeps chain handlers free of\n * per-site `defaultAppName` boilerplate; `_ctxForMethod` injects it.\n */\nconst METHOD_PREFIX_TO_APP_NAME: Record<string, string> = {\n evm: 'Ethereum',\n btc: 'Bitcoin',\n sol: 'Solana',\n tron: 'Tron',\n};\n\nconst HARDWARE_ERROR_CODE_VALUES = new Set<number>(\n Object.values(HardwareErrorCode).filter((value): value is number => typeof value === 'number')\n);\n\n// Slow-advertising peripherals (screensaver, post-unpair) can advertise on\n// ~1s intervals, so the 800ms list-scan window is too tight at connect time.\nconst BLE_CONNECT_SCAN_TIMEOUT_MS = 1500;\n\n// ---------------------------------------------------------------------------\n// Default signer kit importer (webpack/rspack — uses \"exports\" field)\n// ---------------------------------------------------------------------------\n\n/**\n * Default importer for Ledger signer kit packages.\n * Uses bare module specifiers — works with bundlers that support \"exports\".\n * Metro (React Native) can't resolve these; pass a custom importer that\n * uses CJS paths (e.g. `@ledgerhq/device-signer-kit-ethereum/lib/cjs/index.js`).\n */\nasync function defaultLedgerKitImporter(pkg: string): Promise<any> {\n switch (pkg) {\n case '@ledgerhq/device-management-kit':\n return import('@ledgerhq/device-management-kit');\n case '@ledgerhq/device-signer-kit-ethereum':\n return import('@ledgerhq/device-signer-kit-ethereum');\n case '@ledgerhq/device-signer-kit-bitcoin':\n return import('@ledgerhq/device-signer-kit-bitcoin');\n case '@ledgerhq/device-signer-kit-solana':\n return import('@ledgerhq/device-signer-kit-solana');\n case '@ledgerhq/context-module':\n return import('@ledgerhq/context-module');\n default:\n throw new Error(`Unknown Ledger kit package: ${pkg}`);\n }\n}\n\n// Mirrors _getEthSigner in chains/evm.ts.\nasync function _getDeviceApps(ctx: ConnectorContext, sessionId: string): Promise<DeviceApps> {\n const manager = await ctx.getDeviceAppsManager();\n const apps = await manager.getOrCreate(sessionId);\n apps.onInteraction = (interaction: string) => {\n ctx.emit('ui-event', {\n type: collapseSignerInteraction(interaction),\n payload: { sessionId },\n });\n };\n apps.onRegisterCanceller = cancel => {\n ctx.registerCanceller(sessionId, cancel);\n };\n return apps;\n}\n\n// ---------------------------------------------------------------------------\n// LedgerConnectorBase\n// ---------------------------------------------------------------------------\n\n/**\n * Shared base class for Ledger IConnector implementations.\n *\n * Encapsulates all shared logic: device discovery, connection management,\n * method dispatch (EVM / BTC / SOL / TRON), signer lifecycle, event emission,\n * and error handling.\n *\n * Chain-specific method implementations live in `./chains/` and receive\n * a ConnectorContext that exposes shared helpers.\n *\n * Subclasses only need to:\n * 1. Supply a transport factory via the constructor.\n * 2. Optionally override `_resolveConnectId()` for transport-specific\n * device identity resolution.\n *\n * Invariant: one instance = one transport. `connectionType` is fixed at\n * construction. To switch transport (e.g. desktop BLE ↔ WebHID), the host\n * must build a new connector instance and replace the old one — don't add\n * multiple transports to a single instance. Lifting this constraint would\n * require routing `connectionType` from `descriptor.transport` per-device\n * and updating every `this.connectionType` branch in this file.\n */\nexport class LedgerConnectorBase implements IConnector {\n private _deviceManager: LedgerDeviceManager | null = null;\n\n private _signerManager: SignerManager | null = null;\n\n private _deviceAppsManager: DeviceAppsManager | null = null;\n\n private _dmk: DeviceManagementKit | null = null;\n\n private readonly _eventHandlers = new Map<\n ConnectorEventType,\n Set<EventHandler<ConnectorEventType>>\n >();\n\n private readonly _providedDmk: DeviceManagementKit | undefined;\n\n private readonly _createTransport: TransportFactory;\n\n public readonly connectionType: ConnectionType;\n\n // ---------------------------------------------------------------------------\n // Per-session DeviceAction cancellers\n //\n // Each chain handler registers its active DeviceAction's canceller via\n // ctx.registerCanceller(sessionId, cancel) and clears it on completion.\n // IConnector.cancel(sessionId) invokes the registered canceller, which\n // unsubscribes the observable and releases DMK's IntentQueue slot.\n // ---------------------------------------------------------------------------\n private readonly _cancellers = new Map<string, (reason?: CancelReason) => void>();\n\n // ---------------------------------------------------------------------------\n // Per-session DMK state subscriptions\n //\n // DMK only emits `device-disconnect` on the connector when `disconnect()`\n // is called explicitly. To pick up autonomous disconnects (USB unplug,\n // BLE drop, device sleep, DMK transport reset) we subscribe to\n // `_dmk.getDeviceSessionState({sessionId})` per active session and emit\n // `device-disconnect` ourselves the moment DMK reports the device went\n // to NOT_CONNECTED. The subscription is torn down on disconnect /\n // reset / observable completion to avoid leaks.\n // ---------------------------------------------------------------------------\n private readonly _sessionStateSubs = new Map<string, { unsubscribe: () => void }>();\n\n /**\n * Resolves a Ledger signer kit module by package name.\n * Override via constructor to use CJS paths for Metro (React Native).\n * Default: dynamic import with bare specifier (webpack/rspack).\n */\n protected _importLedgerKit: (pkg: string) => Promise<any>;\n\n /** Context object passed to per-chain handler functions. */\n private readonly _ctx: ConnectorContext;\n\n /** When true, BLE direct-connect throws NotAdvertising if the pre-flight\n * scan can't see the device — guard for GATT stacks that wedge on\n * non-advertising peripherals (iOS). */\n private readonly _requirePreFlightScan: boolean;\n\n constructor(\n createTransport: TransportFactory,\n options?: {\n connectionType?: ConnectionType;\n dmk?: DeviceManagementKit;\n /**\n * Override how `@ledgerhq/device-signer-kit-*` packages are imported.\n * Default: `(pkg) => import(pkg)` — works with webpack/rspack.\n * For Metro (React Native): pass a resolver that uses CJS paths.\n */\n importLedgerKit?: (pkg: string) => Promise<any>;\n /** Default false. RN-iOS subclass should pass `true`. */\n requirePreFlightScan?: boolean;\n }\n ) {\n this._createTransport = createTransport;\n this.connectionType = options?.connectionType ?? 'usb';\n this._providedDmk = options?.dmk;\n this._importLedgerKit = options?.importLedgerKit ?? defaultLedgerKitImporter;\n this._requirePreFlightScan = options?.requirePreFlightScan ?? false;\n if (this._providedDmk) {\n this._initManagers(this._providedDmk);\n }\n\n // Build the context that chain handlers use\n this._ctx = {\n emit: <K extends ConnectorEventType>(event: K, data: ConnectorEventMap[K]) =>\n this._emit(event, data),\n invalidateSession: sid => this._invalidateSession(sid),\n wrapError: (err, opts) => this._wrapError(err, opts),\n getOrCreateDmk: () => this._getOrCreateDmk(),\n getDeviceManager: () => this._getDeviceManager(),\n getSignerManager: () => this._getSignerManager(),\n getDeviceAppsManager: () => this._getDeviceAppsManager(),\n clearAllSigners: () => this._signerManager?.clearAll(),\n replaceSession: (oldSid, newSid) => this._replaceSession(oldSid, newSid),\n registerCanceller: (sid, cancel) => this._cancellers.set(sid, cancel),\n clearCanceller: sid => this._cancellers.delete(sid),\n importLedgerKit: this._importLedgerKit,\n };\n }\n\n // ---------------------------------------------------------------------------\n // Protected — hooks for subclasses\n // ---------------------------------------------------------------------------\n\n /**\n * Resolve the connectId for a discovered device descriptor.\n * Default: use the DMK path (ephemeral UUID).\n * Override in subclasses only when the public connectId differs from the transport path.\n */\n protected _resolveConnectId(descriptor: DeviceDescriptor): string {\n return descriptor.path;\n }\n\n /**\n * Authoritative discovery for this transport. Default = enumerate snapshot\n * (USB/HID). BLE overrides to drive from a live scan window since DMK's\n * enumerate() cache survives peripherals going offline.\n */\n protected async _discoverDescriptors(dm: LedgerDeviceManager): Promise<DeviceDescriptor[]> {\n let descriptors = await dm.enumerate();\n if (descriptors.length === 0) {\n try {\n await dm.requestDevice();\n } catch {\n // User may cancel the permission dialog\n }\n descriptors = await dm.enumerate();\n }\n return descriptors;\n }\n\n // ---------------------------------------------------------------------------\n // IConnector -- Device discovery\n //\n // Discovery never throws on multiple USB devices — it returns the full list.\n // The \"connect exactly one device\" rule is enforced upstream: an explicit\n // connectId connects that device (or fails as not-found), and only the\n // no-connectId USB path rejects when more than one device is present\n // (see LedgerAdapter._connectFirstOrSelect).\n // ---------------------------------------------------------------------------\n\n async searchDevices(): Promise<ConnectorDevice[]> {\n const dm = await this._getDeviceManager();\n\n const descriptors = await this._discoverDescriptors(dm);\n const resolvedDescriptors = descriptors.map(d => ({\n descriptor: d,\n connectId: this._resolveConnectId(d),\n }));\n const result: ConnectorDevice[] = resolvedDescriptors.map(({ descriptor: d, connectId }) => ({\n connectId,\n deviceId: d.path,\n name: d.name || d.type || 'Ledger',\n model: d.type,\n modelName: d.modelName,\n rssi: d.rssi,\n isConnectable: d.isConnectable,\n serialNumber: d.serialNumber,\n }));\n debugLog(\n `[DMK] connector.searchDevices() return count=${result.length} ids=[${result\n .map(r => r.connectId)\n .join(',')}] paths=[${result.map(r => r.deviceId).join(',')}]`\n );\n return result;\n }\n\n // ---------------------------------------------------------------------------\n // IConnector -- Connection\n // ---------------------------------------------------------------------------\n\n async connect(deviceId?: string): Promise<ConnectorSession> {\n // Trust caller's deviceId — search has already happened upstream\n // (UI scan flow). When caller didn't specify, fall back to a fresh\n // search so we have something to connect to.\n //\n // Only the explicit-connectId path gets the BLE direct-connect treatment.\n const callerSuppliedConnectId = Boolean(deviceId);\n let targetPath = deviceId;\n if (!targetPath) {\n const discovered = await this.searchDevices();\n if (discovered.length === 0) {\n throw new Error(\n `No Ledger device found. Make sure the device is connected${\n isLedgerBleConnectionType(this.connectionType)\n ? ' nearby with Bluetooth enabled'\n : ' via USB'\n } and unlocked.`\n );\n }\n targetPath = discovered[0].deviceId;\n }\n\n const externalConnectId = targetPath;\n\n // No active SMP timeout — let dm.connect resolve/reject naturally based\n // on what DMK / iOS BLE stack actually report. iOS has its own ~30s SMP\n // timeout; we trust it. The previous active 30s timer mis-judged slow-\n // but-successful pairings (user took 35s to confirm passkey).\n // 5min hang ceiling only catches genuine DMK stuck-promise (very rare).\n const HANG_CEILING_MS = 5 * 60_000;\n const dmConnectWithObserve = async (dm: LedgerDeviceManager, path: string): Promise<string> => {\n if (!isLedgerBleConnectionType(this.connectionType)) return dm.connect(path);\n\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n let timedOut = false;\n const connectPromise = dm.connect(path);\n const hangPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n timedOut = true;\n const err = new Error(\n `Ledger BLE connect did not return within ${\n HANG_CEILING_MS / 60_000\n }min — DMK hang fallback.`\n ) as Error & { _tag?: string; code?: number };\n err._tag = ERROR_TAG.BlePairingTimeout;\n err.code = HardwareErrorCode.BlePairingTimeout;\n reject(err);\n }, HANG_CEILING_MS);\n });\n try {\n return await Promise.race([connectPromise, hangPromise]);\n } catch (err) {\n const e = err as {\n _tag?: string;\n message?: string;\n errorCode?: unknown;\n statusCode?: unknown;\n originalError?: { _tag?: string; message?: string };\n };\n debugLog('[DMK] dm.connect rejected — observed:', {\n _tag: e?._tag,\n message: e?.message,\n errorCode: e?.errorCode,\n statusCode: e?.statusCode,\n originalTag: e?.originalError?._tag,\n originalMessage: e?.originalError?.message,\n });\n if (timedOut) {\n void connectPromise.then(\n sessionId => dm.disconnect(sessionId).catch(() => undefined),\n () => undefined\n );\n }\n throw err;\n } finally {\n if (timeoutId) clearTimeout(timeoutId);\n }\n };\n\n // Resolve dm lazily — _resetSignersAndSessions during retry replaces\n // _deviceManager, so capturing it in a closure would use a stale instance\n // whose _discovered Map has been disposed.\n // BLE direct-connect: caller supplied a connectId on a BLE transport.\n const isBleDirectConnect =\n isLedgerBleConnectionType(this.connectionType) && callerSuppliedConnectId;\n\n const throwNotAdvertising = (): never => {\n const err = new Error(\n 'Ledger device is not currently advertising. Wake up and unlock the device, keep it nearby, then try again.'\n ) as Error & { _tag?: string; code?: number };\n err._tag = ERROR_TAG.DeviceNotAdvertising;\n err.code = HardwareErrorCode.DeviceNotFound;\n throw err;\n };\n\n const doConnect = async (path: string): Promise<ConnectorSession> => {\n const dm = await this._getDeviceManager();\n // BLE direct-connect: refresh _discovered (DMK requires it before connect).\n // iOS throws early on empty scan to avoid the ~30s GATT/SMP wedge;\n // others trust the caller and let dm.connect() surface its own error.\n if (isBleDirectConnect && !dm.hasDiscoveredDevice(path)) {\n const live = await dm.getLiveDevices(BLE_CONNECT_SCAN_TIMEOUT_MS);\n if (this._requirePreFlightScan && !live.some(d => d.id === path)) {\n throwNotAdvertising();\n }\n }\n let sessionId: string;\n try {\n sessionId = await dmConnectWithObserve(dm, path);\n } catch (err) {\n // LedgerDeviceManager.connect() tags this when path isn't in _discovered.\n if (\n isBleDirectConnect &&\n (err as { _tag?: string } | null)?._tag === ERROR_TAG.DeviceNotInDiscoveryCache\n ) {\n throwNotAdvertising();\n }\n throw err;\n }\n try {\n this._watchSessionState(sessionId, externalConnectId);\n } catch (subErr) {\n // Subscription failure is fatal (see _watchSessionState) — disconnect\n // the just-created DMK session so connect()'s catch wraps it normally.\n debugLog('[DMK] state subscription failed during connect; disconnecting session:', subErr);\n try {\n await dm.disconnect(sessionId);\n } catch {\n // best-effort cleanup\n }\n throw subErr;\n }\n const info = dm.getDiscoveredDeviceInfo(path);\n const session: ConnectorSession = {\n sessionId,\n deviceInfo: {\n vendor: 'ledger',\n model: info?.model ?? 'unknown',\n modelName: info?.modelName,\n firmwareVersion: 'unknown',\n deviceId: path,\n connectId: externalConnectId,\n connectionType: this.connectionType,\n rssi: info?.rssi,\n capabilities: { persistentDeviceIdentity: false },\n },\n };\n // dm.connect() requires the descriptor in _discovered, so name lookup\n // will succeed; fallback covers any transient race.\n const name = dm.getDeviceName(path) ?? 'Ledger';\n this._emit('device-connect', {\n device: { connectId: externalConnectId, deviceId: path, name },\n });\n return session;\n };\n\n try {\n return await doConnect(targetPath);\n } catch (err) {\n // GATT failed — clean up local state and let the adapter own recovery.\n // We don't search-and-retry here: Layer 1 (`_doConnect` in LedgerAdapter)\n // is the single recovery owner. Doing a second doConnect here just\n // doubles the timeout the user sees before the unlock dialog appears.\n this._resetSignersAndSessions();\n\n // BLE GATT failures split into 3 tags:\n // BlePairingTimeout — our 30s timeout (pre-classified above)\n // BleGattBondingFailed — anything else (PeerRemoved / BleError /\n // iOS SMP reject / unknown transport)\n // DeviceNotAdvertising — pre-GATT scan miss (only from connectDevice)\n if (isLedgerBleConnectionType(this.connectionType)) {\n const tag = (err as { _tag?: string } | null | undefined)?._tag;\n\n // If DMK already gave a recognized tag (locked / disconnected / pairing\n // / transport-class), pass through untouched so SDK classifiers can\n // route on the real cause. We only wrap completely untagged errors.\n if (isKnownConnectionTag(tag)) {\n throw err;\n }\n\n // Untagged failure — wrap as BleGattBondingFailed so upstream still\n // has a code path. Original error preserved on `originalError`.\n const wrapped = new Error(\n 'Ledger Bluetooth pairing failed. Make sure the device is unlocked and nearby, then try again.'\n ) as Error & { _tag?: string; code?: number; originalError?: unknown };\n wrapped._tag = ERROR_TAG.BleGattBondingFailed;\n wrapped.code = HardwareErrorCode.BlePairingTimeout;\n wrapped.originalError = err;\n throw wrapped;\n }\n\n // USB/HID: typed errors flow through unchanged so APDU/transport\n // diagnostics aren't masked. Unknown failure → \"unplugged\".\n if (err && typeof err === 'object' && (err as { _tag?: string })._tag) {\n const taggedError =\n err instanceof Error\n ? err\n : Object.assign(\n new Error((err as { message?: string }).message ?? 'Ledger device error'),\n err\n );\n throw taggedError;\n }\n throw new Error('Ledger device appears unplugged. Plug in the device and try again.');\n }\n }\n\n async disconnect(sessionId: string): Promise<void> {\n if (!this._deviceManager) return;\n\n const deviceId = this._deviceManager.getDeviceId(sessionId);\n this._signerManager?.invalidate(sessionId);\n this._unwatchSessionState(sessionId);\n await this._deviceManager.disconnect(sessionId);\n\n if (deviceId) {\n this._emit('device-disconnect', { connectId: deviceId });\n }\n }\n\n /**\n * Subscribe to DMK's per-session state observable so that any autonomous\n * disconnect (USB unplug, BLE drop, device sleep, transport reset) is\n * surfaced as a `device-disconnect` event — without this, the upstream\n * `LedgerAdapter._sessions` map would hold a dead session entry until\n * the next call hit `DeviceSessionNotFound`.\n *\n * Subscribe failure is fatal — see the inline note at the subscribe call.\n */\n private _watchSessionState(sessionId: string, externalConnectId: string): void {\n const dmk = this._dmk;\n if (!dmk) return;\n const previous = this._sessionStateSubs.get(sessionId);\n if (previous) {\n try {\n previous.unsubscribe();\n } catch {\n // ignore\n }\n }\n // Subscribe failure is fatal: without this subscription we can't detect\n // autonomous disconnect (USB unplug, BLE drop, sleep), which leaks ghost\n // entries into the adapter's _sessions map and can route subsequent calls\n // to the wrong device. Let the error propagate so connect() cleans up the\n // just-created DMK session and fails loudly.\n const sub = dmk.getDeviceSessionState({ sessionId }).subscribe({\n next: (state: { deviceStatus?: string }) => {\n // String-compare against DeviceStatus.NOT_CONNECTED (\"NOT CONNECTED\")\n // to avoid pulling the runtime enum import (kept type-only for\n // Metro/RN compatibility — see _importLedgerKit).\n if (state?.deviceStatus === 'NOT CONNECTED') {\n this._handleAutonomousDisconnect(sessionId, externalConnectId);\n }\n },\n error: () => {\n // DMK closed the observable abnormally — treat as disconnect.\n this._handleAutonomousDisconnect(sessionId, externalConnectId);\n },\n complete: () => {\n // Observable completed — session is gone from DMK's POV.\n this._handleAutonomousDisconnect(sessionId, externalConnectId);\n },\n });\n this._sessionStateSubs.set(sessionId, sub);\n }\n\n private _unwatchSessionState(sessionId: string): void {\n const sub = this._sessionStateSubs.get(sessionId);\n if (!sub) return;\n try {\n sub.unsubscribe();\n } catch {\n // ignore\n }\n this._sessionStateSubs.delete(sessionId);\n }\n\n private _handleAutonomousDisconnect(sessionId: string, externalConnectId: string): void {\n if (!this._sessionStateSubs.has(sessionId)) return; // already handled\n debugLog(\n '[DMK] autonomous disconnect detected — sessionId:',\n sessionId,\n 'connectId:',\n externalConnectId\n );\n this._unwatchSessionState(sessionId);\n this._signerManager?.invalidate(sessionId);\n this._cancellers.get(sessionId)?.({\n code: HardwareErrorCode.DeviceDisconnected,\n tag: 'DeviceDisconnected',\n message: 'Device disconnected',\n });\n this._cancellers.delete(sessionId);\n this._emit('device-disconnect', { connectId: externalConnectId });\n }\n\n // ---------------------------------------------------------------------------\n // IConnector -- Method dispatch\n // ---------------------------------------------------------------------------\n\n // Device failures are returned as a `ConnectorCallResult` (success:false),\n // never thrown — so they cross the IHardwareBridge / extension offscreen↔SW\n // boundary as plain data instead of being mangled by the JsBridge error\n // whitelist (`toPlainError`). The SW-side adapter rehydrates and re-throws\n // locally (see LedgerAdapter._unwrapConnectorResult).\n async call(sessionId: string, method: string, params: unknown): Promise<ConnectorCallResult> {\n debugLog('[DMK] call:', method, JSON.stringify(params));\n try {\n const payload = await this._dispatch(sessionId, method, params);\n return { success: true, payload };\n } catch (err) {\n // True chain-app stuck (APDU 0x6901): user must back out of the\n // app on the device — keep the \"press both buttons to exit\" message.\n if (isAppStuckByApdu(err)) {\n return {\n success: false,\n error: serializeConnectorError(\n Object.assign(new Error('Ledger app is unresponsive'), {\n code: HardwareErrorCode.DeviceAppStuck,\n _tag: ERROR_TAG.DeviceAppStuck,\n originalError: err,\n })\n ),\n };\n }\n // DMK transport queue wedged (AlreadySendingApdu / UnknownDeviceExchange):\n // device + app are fine, only our SDK-side comms got tangled. Surface\n // as TransportError so the user sees a \"communication interrupted,\n // please retry\" message instead of a misleading \"exit app\" prompt.\n // Layer 2 (LedgerAdapter._runConnectorCall) will reset the connector\n // before re-throwing so the next call rebuilds a clean DMK instance.\n if (isTransportStuck(err)) {\n return {\n success: false,\n error: serializeConnectorError(\n Object.assign(new Error('Device communication interrupted, please retry'), {\n code: HardwareErrorCode.TransportError,\n _tag: ERROR_TAG.DeviceTransportStuck,\n originalError: err,\n })\n ),\n };\n }\n return { success: false, error: serializeConnectorError(err) };\n }\n }\n\n private async _dispatch(sessionId: string, method: string, params: unknown): Promise<unknown> {\n // Bind the chain's Ledger app name to ctx.wrapError once per dispatch so\n // chain handlers can call `ctx.wrapError(err)` with no per-site appName.\n const ctx = this._ctxForMethod(method);\n switch (method) {\n // EVM\n case 'evmGetAddress':\n return evmGetAddress(ctx, sessionId, params as EvmGetAddressCallParams);\n case 'evmSignTransaction':\n return evmSignTransaction(ctx, sessionId, params as EvmSignTransactionCallParams);\n case 'evmSignMessage':\n return evmSignMessage(ctx, sessionId, params as EvmSignMessageCallParams);\n case 'evmSignTypedData':\n return evmSignTypedData(ctx, sessionId, params as EvmSignTypedDataCallParams);\n // BTC\n case 'btcGetAddress':\n return btcGetAddress(ctx, sessionId, params as BtcGetAddressCallParams);\n case 'btcGetPublicKey':\n return btcGetPublicKey(ctx, sessionId, params as BtcGetPublicKeyCallParams);\n case 'btcSignTransaction':\n return btcSignTransaction(ctx, sessionId, params as BtcSignTransactionCallParams);\n case 'btcSignPsbt':\n return btcSignPsbt(ctx, sessionId, params as BtcSignPsbtCallParams);\n case 'btcSignMessage':\n return btcSignMessage(ctx, sessionId, params as BtcSignMessageCallParams);\n case 'btcGetMasterFingerprint':\n return btcGetMasterFingerprint(\n ctx,\n sessionId,\n params as { skipOpenApp?: boolean } | undefined\n );\n // SOL\n case 'solGetAddress':\n return solGetAddress(ctx, sessionId, params as SolGetAddressCallParams);\n case 'solSignTransaction':\n return solSignTransaction(ctx, sessionId, params as SolSignTransactionCallParams);\n case 'solSignMessage':\n return solSignMessage(ctx, sessionId, params as SolSignMessageCallParams);\n // TRON\n case 'tronGetAddress':\n return tronGetAddress(ctx, sessionId, params as TronGetAddressCallParams);\n case 'tronSignTransaction':\n return tronSignTransaction(ctx, sessionId, params as TronSignTransactionCallParams);\n case 'tronSignMessage': {\n // Explicit public→internal mapping so a field-name drift fails at\n // compile time, not silently at runtime (see bug: public `messageHex`\n // vs internal `messageHex` field name enforcement).\n const p = params as TronSignMsgParams;\n const internalParams: TronSignMessageCallParams = {\n path: p.path,\n messageHex: p.messageHex,\n };\n return tronSignMessage(ctx, sessionId, internalParams);\n }\n // OS-level device management — symmetric to chain handlers.\n // Each case uses try/catch/finally to mirror chain handlers: catch wraps\n // raw DMK errors (so mapLedgerError / isOutOfMemoryError run) and\n // invalidates the session (so a stale sid isn't reused by subsequent\n // listInstalledApps / signTransaction calls).\n case 'installApp': {\n const p = params as InstallAppCallParams;\n const apps = await _getDeviceApps(ctx, sessionId);\n try {\n // Progress callback is built here (not on params) so the function ref\n // never crosses the IHardwareBridge boundary. Emits as a `ui-event`\n // AppInstallProgress variant; the adapter re-keys sessionId →\n // connectId before re-emitting to its public typed emitter.\n return await apps.install(p.appName, ({ progress }) => {\n ctx.emit('ui-event', {\n type: EConnectorInteraction.AppInstallProgress,\n payload: {\n sessionId,\n appName: p.appName,\n progress,\n },\n });\n });\n } catch (err) {\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err);\n } finally {\n ctx.clearCanceller(sessionId);\n }\n }\n case 'listInstalledApps': {\n const apps = await _getDeviceApps(ctx, sessionId);\n try {\n return await apps.listInstalled(params as ListInstalledAppsCallParams);\n } catch (err) {\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err);\n } finally {\n ctx.clearCanceller(sessionId);\n }\n }\n case 'listAvailableApps': {\n const apps = await _getDeviceApps(ctx, sessionId);\n try {\n return await apps.listAvailable();\n } catch (err) {\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err);\n } finally {\n ctx.clearCanceller(sessionId);\n }\n }\n case 'getFirmwareVersion': {\n const apps = await _getDeviceApps(ctx, sessionId);\n try {\n return await apps.getFirmwareVersion();\n } catch (err) {\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err);\n } finally {\n ctx.clearCanceller(sessionId);\n }\n }\n case 'getDeviceInfo': {\n const apps = await _getDeviceApps(ctx, sessionId);\n try {\n return await apps.getDeviceInfo();\n } catch (err) {\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err);\n } finally {\n ctx.clearCanceller(sessionId);\n }\n }\n default:\n throw new Error(`LedgerConnector: unknown method \"${method}\"`);\n }\n }\n\n async cancel(sessionId: string): Promise<void> {\n // Invoke the active DeviceAction canceller (registered by the chain handler).\n // This unsubscribes the observable and releases DMK's IntentQueue slot so\n // the next call on this session isn't blocked behind an orphaned intent.\n //\n // Note: Ledger devices have no hardware-level APDU abort. If the user has\n // an on-device confirmation prompt pending, it will remain until the user\n // presses Reject or the device times out.\n const cancel = this._cancellers.get(sessionId);\n if (cancel) {\n this._cancellers.delete(sessionId);\n try {\n cancel();\n } catch {\n // canceller may have already been invoked; ignore\n }\n }\n }\n\n uiResponse(_response: UiResponseEvent): void {\n // Ledger does not use interactive UI responses (PIN/passphrase)\n }\n\n // ---------------------------------------------------------------------------\n // IConnector -- Events\n // ---------------------------------------------------------------------------\n\n on<K extends ConnectorEventType>(event: K, handler: (data: ConnectorEventMap[K]) => void): void {\n if (!this._eventHandlers.has(event)) {\n this._eventHandlers.set(event, new Set());\n }\n this._eventHandlers.get(event)!.add(handler as EventHandler<ConnectorEventType>);\n }\n\n off<K extends ConnectorEventType>(event: K, handler: (data: ConnectorEventMap[K]) => void): void {\n this._eventHandlers.get(event)?.delete(handler as EventHandler<ConnectorEventType>);\n }\n\n // ---------------------------------------------------------------------------\n // IConnector -- Reset\n // ---------------------------------------------------------------------------\n\n reset(): void {\n this._resetAll();\n }\n\n // ---------------------------------------------------------------------------\n // Private -- DMK / Manager lifecycle\n // ---------------------------------------------------------------------------\n\n /**\n * Lazily create or return the DMK instance.\n * If a DMK was provided via constructor, it is used directly.\n * Otherwise, one is created via the transport factory.\n */\n protected async _getOrCreateDmk(): Promise<DeviceManagementKit> {\n debugLog(\n '[DMK] _getOrCreateDmk called, _dmk exists:',\n !!this._dmk,\n '_providedDmk exists:',\n !!this._providedDmk\n );\n if (this._dmk) return this._dmk;\n\n if (this._providedDmk) {\n this._dmk = this._providedDmk;\n return this._dmk;\n }\n\n const { DeviceManagementKitBuilder } = await this._importLedgerKit(\n '@ledgerhq/device-management-kit'\n );\n const transportFactory = await this._createTransport();\n\n debugLog('[DMK] _getOrCreateDmk: transportFactory type:', typeof transportFactory);\n\n const dmk: DeviceManagementKit = new DeviceManagementKitBuilder()\n .addTransport(transportFactory)\n .build();\n this._dmk = dmk;\n\n debugLog('[DMK] _getOrCreateDmk: DMK created');\n\n return dmk;\n }\n\n private _initManagers(dmk: DeviceManagementKit): void {\n this._dmk = dmk;\n this._deviceManager = new LedgerDeviceManager(dmk);\n\n // Pass a custom ETH signer builder that uses _importLedgerKit,\n // so the BLE connector's CJS override applies to ETH too.\n const importKit = this._importLedgerKit;\n this._signerManager = new SignerManager(dmk, async args => {\n const mod = await importKit('@ledgerhq/device-signer-kit-ethereum');\n return new mod.SignerEthBuilder(args);\n });\n this._deviceAppsManager = new DeviceAppsManager(dmk, importKit);\n }\n\n private async _getDeviceManager(): Promise<LedgerDeviceManager> {\n if (this._deviceManager) return this._deviceManager;\n\n const dmk = await this._getOrCreateDmk();\n this._initManagers(dmk);\n return this._deviceManager!;\n }\n\n private async _getSignerManager(): Promise<SignerManager> {\n if (!this._signerManager) {\n const dmk = await this._getOrCreateDmk();\n this._initManagers(dmk);\n }\n return this._signerManager!;\n }\n\n private async _getDeviceAppsManager(): Promise<DeviceAppsManager> {\n if (!this._deviceAppsManager) {\n const dmk = await this._getOrCreateDmk();\n this._initManagers(dmk);\n }\n return this._deviceAppsManager!;\n }\n\n private _invalidateSession(sessionId: string): void {\n this._signerManager?.invalidate(sessionId);\n }\n\n /**\n * Replace an old session with a new one after app switch.\n * Emits device-connect so the adapter updates its _sessions Map.\n */\n private _replaceSession(oldSessionId: string, _newSessionId: string): void {\n const dm = this._deviceManager;\n if (!dm) return;\n\n const oldDeviceId = dm.getDeviceId(oldSessionId);\n const connectId = oldDeviceId;\n\n // Invalidate old signer cache\n this._signerManager?.invalidate(oldSessionId);\n\n // Emit device-connect so the adapter picks up the new session\n if (connectId) {\n this._emit('device-connect', {\n device: {\n connectId,\n deviceId: connectId,\n name: 'Ledger',\n },\n });\n }\n }\n\n /**\n * Light reset: clear signer/session state but keep DMK alive.\n * Used by connect() retry — we want to re-discover with the same transport.\n *\n * Note: drops the device manager but tears down its RxJS subs first via\n * disposeKeepingDmk(). Bare null-assignment would leak _listenSub /\n * _discoverySub and double-scan after the next _initManagers().\n */\n private _resetSignersAndSessions(): void {\n debugLog('[DMK] _resetSignersAndSessions called');\n this._signerManager?.clearAll();\n this._signerManager = null;\n this._deviceAppsManager?.clearAll();\n this._deviceAppsManager = null;\n this._deviceManager?.disposeKeepingDmk();\n this._deviceManager = null;\n }\n\n private _resetAll(): void {\n debugLog('[DMK] _resetAll called');\n // Cancel any in-flight DeviceActions so their observables unsubscribe\n // and DMK's intent queues don't keep orphaned slots alive.\n for (const cancel of this._cancellers.values()) {\n try {\n cancel();\n } catch {\n // already cancelled / settled — ignore\n }\n }\n this._cancellers.clear();\n // Tear down per-session state subscriptions so we don't keep observing\n // a DMK we're about to drop.\n for (const sub of this._sessionStateSubs.values()) {\n try {\n sub.unsubscribe();\n } catch {\n // ignore\n }\n }\n this._sessionStateSubs.clear();\n this._signerManager?.clearAll();\n this._deviceAppsManager?.clearAll();\n this._deviceManager?.dispose();\n this._deviceManager = null;\n this._signerManager = null;\n this._deviceAppsManager = null;\n this._dmk = null;\n }\n\n // ---------------------------------------------------------------------------\n // Private -- Events\n // ---------------------------------------------------------------------------\n\n protected _emit<K extends ConnectorEventType>(event: K, data: ConnectorEventMap[K]): void {\n const handlers = this._eventHandlers.get(event);\n if (handlers) {\n for (const handler of handlers) {\n try {\n handler(data);\n } catch {\n // Don't let listener errors break the connector\n }\n }\n }\n }\n\n // ---------------------------------------------------------------------------\n // Private -- Error handling\n // ---------------------------------------------------------------------------\n\n /**\n * Return a per-call ctx with the chain's Ledger app name pre-bound to\n * wrapError, so chain handlers don't need to repeat `{ defaultAppName: 'X' }`\n * at every catch site. Falls through unchanged for unknown methods.\n */\n private _ctxForMethod(method: string): ConnectorContext {\n const prefix = /^(evm|btc|sol|tron)/.exec(method)?.[1];\n const defaultAppName = prefix ? METHOD_PREFIX_TO_APP_NAME[prefix] : undefined;\n if (!defaultAppName) return this._ctx;\n return {\n ...this._ctx,\n wrapError: (err, opts) => this._wrapError(err, { defaultAppName, ...opts }),\n };\n }\n\n private _wrapError(err: unknown, opts?: WrapErrorOptions): Error {\n const src = (err && typeof err === 'object' ? err : {}) as Record<string, unknown>;\n const hasSerializedCode =\n typeof src.code === 'number' && HARDWARE_ERROR_CODE_VALUES.has(src.code);\n const mapped = hasSerializedCode\n ? {\n code: src.code as HardwareErrorCode,\n message: typeof src.message === 'string' ? src.message : 'Unknown Ledger error',\n appName: typeof src.appName === 'string' ? src.appName : opts?.defaultAppName,\n }\n : mapLedgerError(err, opts);\n const error = new Error(mapped.message);\n // Preserve DMK / EthAppCommandError fields so downstream classifiers\n // (including cross-layer `wrapError` → caller re-classification) can still\n // key on APDU code and step context attached by deviceActionToPromise.\n Object.assign(error, {\n code: mapped.code,\n appName: mapped.appName,\n _tag: src._tag,\n errorCode: src.errorCode,\n _lastStep: src._lastStep,\n _deviceActionSteps: src._deviceActionSteps,\n });\n // Non-enumerable: DMK errors can carry APDU payloads / signing\n // intermediates that shouldn't leak into JSON.stringify / log transports.\n Object.defineProperty(error, 'originalError', {\n value: err,\n configurable: true,\n enumerable: false,\n writable: true,\n });\n return error;\n }\n}\n","import { ERROR_TAG } from '../errors';\nimport { debugError, debugLog } from '../utils/debugLog';\n\nimport type { DeviceChangeEvent, DeviceDescriptor } from '@onekeyfe/hwk-adapter-core';\nimport type { DeviceManagementKit } from '@ledgerhq/device-management-kit';\nimport type { DmkDiscoveredDevice } from '../types';\n\n/**\n * Manages device discovery, connection, and session tracking.\n * Wraps DMK's Observable APIs into simpler imperative calls.\n */\nexport class LedgerDeviceManager {\n private readonly _dmk: DeviceManagementKit;\n\n private readonly _discovered = new Map<string, DmkDiscoveredDevice>();\n\n private readonly _sessions = new Map<string, string>(); // deviceId → sessionId\n\n private readonly _sessionToDevice = new Map<string, string>(); // sessionId → deviceId\n\n private _listenSub: { unsubscribe: () => void } | null = null;\n\n constructor(dmk: DeviceManagementKit) {\n this._dmk = dmk;\n }\n\n /**\n * One-shot enumeration: subscribe to listenToAvailableDevices,\n * take the first emission, unsubscribe, return DeviceDescriptors.\n */\n enumerate(): Promise<DeviceDescriptor[]> {\n debugLog('[DMK] enumerate() called, dmk exists:', !!this._dmk);\n return new Promise<DeviceDescriptor[]>(resolve => {\n let resolved = false;\n let syncResult: DmkDiscoveredDevice[] | null = null;\n let sub: { unsubscribe: () => void } | null = null;\n\n sub = this._dmk.listenToAvailableDevices({}).subscribe({\n next: devices => {\n if (resolved) return;\n resolved = true;\n this._discovered.clear();\n debugLog(\n `[DMK] enumerate count=${devices.length} ids=[${devices.map(d => d.id).join(',')}]`\n );\n for (const d of devices) {\n this._discovered.set(d.id, d);\n }\n // If sub is already assigned (async emission), resolve and unsubscribe immediately\n if (sub) {\n sub.unsubscribe();\n resolve(\n devices.map(d => ({\n path: d.id,\n type: d.deviceModel.model,\n modelName: d.deviceModel.name,\n name: d.name,\n transport: d.transport,\n rssi: d.rssi,\n }))\n );\n } else {\n // Synchronous emission — sub not yet assigned, defer to after subscribe()\n syncResult = devices;\n }\n },\n error: () => {\n if (!resolved) {\n resolved = true;\n resolve([]);\n }\n },\n });\n\n // If BehaviorSubject fired synchronously, sub is now assigned\n if (syncResult !== null) {\n sub.unsubscribe();\n const devices = syncResult as DmkDiscoveredDevice[];\n resolve(\n devices.map(d => ({\n path: d.id,\n type: d.deviceModel.model,\n modelName: d.deviceModel.name,\n name: d.name,\n transport: d.transport,\n rssi: d.rssi,\n }))\n );\n }\n });\n }\n\n /**\n * Continuous listening: tracks device connect/disconnect via diffing.\n */\n listen(onChange: (event: DeviceChangeEvent) => void): void {\n this.stopListening();\n let previousIds = new Set<string>();\n\n this._listenSub = this._dmk.listenToAvailableDevices({}).subscribe({\n next: devices => {\n const currentIds = new Set(devices.map(d => d.id));\n\n for (const d of devices) {\n this._discovered.set(d.id, d);\n debugLog('[DMK] listen device:', d.id, d.name);\n if (!previousIds.has(d.id)) {\n onChange({\n type: 'device-connected',\n descriptor: {\n path: d.id,\n type: d.deviceModel.model,\n modelName: d.deviceModel.name,\n name: d.name,\n transport: d.transport,\n rssi: d.rssi,\n },\n });\n }\n }\n for (const id of previousIds) {\n if (!currentIds.has(id)) {\n this._discovered.delete(id);\n onChange({ type: 'device-disconnected', descriptor: { path: id } });\n }\n }\n previousIds = currentIds;\n },\n });\n }\n\n stopListening(): void {\n this._listenSub?.unsubscribe();\n this._listenSub = null;\n }\n\n /**\n * Resolve to the latest snapshot of advertising devices observed within\n * `timeoutMs`. Rewrites `_discovered` so it tracks the live list.\n *\n * `listenToAvailableDevices` is a BehaviorSubject — it emits the cached\n * list on subscribe and *only* re-emits when the list changes. A stable\n * list of currently-advertising devices therefore produces only the\n * subscription frame; treating that frame as \"fossil to be discarded\"\n * caused devices to flicker in/out of the UI as searches alternated\n * between \"saw a change frame\" and \"saw only the cached frame\".\n *\n * The window still gives a chance for the active scan to update the list\n * (e.g. drop a peripheral that just stopped broadcasting), but if nothing\n * changes we trust the snapshot — DMK silence on a stable list means\n * \"everything's still there\".\n */\n getLiveDevices(timeoutMs = 1500): Promise<DmkDiscoveredDevice[]> {\n debugLog(`[DMK] getLiveDevices() called, timeoutMs=${timeoutMs}`);\n // Ensure a discovery is in flight; no-op if already scanning.\n void this.requestDevice();\n\n return new Promise<DmkDiscoveredDevice[]>(resolve => {\n let done = false;\n let lastSeen: DmkDiscoveredDevice[] = [];\n let sub: { unsubscribe: () => void } | null = null;\n\n const finish = (devices: DmkDiscoveredDevice[]) => {\n if (done) return;\n done = true;\n sub?.unsubscribe();\n clearTimeout(timer);\n this._discovered.clear();\n for (const d of devices) this._discovered.set(d.id, d);\n debugLog(\n `[DMK] getLiveDevices() resolved count=${devices.length} ids=[${devices\n .map(d => d.id)\n .join(',')}]`\n );\n resolve(devices);\n };\n\n // On timeout, accept whatever we last saw.\n const timer = setTimeout(() => finish(lastSeen), timeoutMs);\n\n sub = this._dmk.listenToAvailableDevices({}).subscribe({\n next: devices => {\n lastSeen = devices;\n },\n error: err => {\n debugError('[DMK] getLiveDevices() error:', err);\n finish(lastSeen);\n },\n complete: () => finish(lastSeen),\n });\n });\n }\n\n /**\n * Trigger browser device selection (WebHID requestDevice).\n * Starts discovery for a short period, then stops.\n */\n /**\n * Start BLE discovery if not already running.\n * Does NOT stop — DMK keeps scanning in the background so that\n * listenToAvailableDevices() always has fresh data.\n */\n private _discoverySub: { unsubscribe: () => void } | null = null;\n\n requestDevice(): Promise<void> {\n if (this._discoverySub) {\n // Already scanning\n return Promise.resolve();\n }\n debugLog('[DMK] requestDevice() starting persistent BLE scan');\n this._discoverySub = this._dmk.startDiscovering({}).subscribe({\n next: d => {\n debugLog('[DMK] BLE discovered:', d.name || d.id);\n this._discovered.set(d.id, d);\n },\n error: err => {\n debugError('[DMK] BLE scan error:', err);\n this._discoverySub = null;\n },\n });\n return Promise.resolve();\n }\n\n /** Lookup a previously-discovered device's display name. */\n getDeviceName(deviceId: string): string | undefined {\n return this._discovered.get(deviceId)?.name;\n }\n\n /** Lookup minimal model/signal info from a previously-discovered device. */\n getDiscoveredDeviceInfo(\n deviceId: string\n ): { model?: string; modelName?: string; name?: string; rssi?: number | null } | undefined {\n const d = this._discovered.get(deviceId);\n if (!d) return undefined;\n return {\n model: d.deviceModel?.model,\n modelName: d.deviceModel?.name,\n name: d.name,\n rssi: d.rssi,\n };\n }\n\n hasDiscoveredDevice(deviceId: string): boolean {\n return this._discovered.has(deviceId);\n }\n\n /** Connect to a previously discovered device. Returns sessionId. */\n async connect(deviceId: string): Promise<string> {\n const device = this._discovered.get(deviceId);\n if (!device) {\n const err = new Error(\n `Device \"${deviceId}\" not found in discovery cache. Call enumerate() or listen() first.`\n ) as Error & { _tag?: string };\n err._tag = ERROR_TAG.DeviceNotInDiscoveryCache;\n throw err;\n }\n const sessionId = await this._dmk.connect({ device });\n this._sessions.set(deviceId, sessionId);\n this._sessionToDevice.set(sessionId, deviceId);\n return sessionId;\n }\n\n /** Disconnect a session. */\n async disconnect(sessionId: string): Promise<void> {\n await this._dmk.disconnect({ sessionId });\n const deviceId = this._sessionToDevice.get(sessionId);\n if (deviceId) this._sessions.delete(deviceId);\n this._sessionToDevice.delete(sessionId);\n }\n\n getSessionId(deviceId: string): string | undefined {\n return this._sessions.get(deviceId);\n }\n\n getDeviceId(sessionId: string): string | undefined {\n return this._sessionToDevice.get(sessionId);\n }\n\n /** Get the underlying DMK instance (needed by SignerManager). */\n getDmk(): DeviceManagementKit {\n return this._dmk;\n }\n\n stopDiscovery(): void {\n if (this._discoverySub) {\n this._discoverySub.unsubscribe();\n this._discoverySub = null;\n this._dmk.stopDiscovering();\n }\n }\n\n dispose(): void {\n this.stopListening();\n this.stopDiscovery();\n this._discovered.clear();\n this._sessions.clear();\n this._sessionToDevice.clear();\n this._dmk.close();\n }\n\n /**\n * Tear down RxJS subscriptions and local state without closing the DMK.\n * For light-reset paths that want to drop session state but keep the\n * underlying transport alive for retry. Call this instead of orphaning\n * the manager — bare null assignment leaks _listenSub / _discoverySub.\n */\n disposeKeepingDmk(): void {\n this.stopListening();\n this.stopDiscovery();\n this._discovered.clear();\n this._sessions.clear();\n this._sessionToDevice.clear();\n }\n}\n","import { SignerEthBuilder } from '@ledgerhq/device-signer-kit-ethereum';\nimport { ContextModuleBuilder } from '@ledgerhq/context-module';\n\nimport { SignerEth } from './SignerEth';\nimport { debugLog } from '../utils/debugLog';\n\nimport type { DeviceManagementKit } from '@ledgerhq/device-management-kit';\nimport type { SignerEth as ISdkSignerEth } from '@ledgerhq/device-signer-kit-ethereum';\nimport type { ContextModule } from '@ledgerhq/context-module';\n\ntype SignerEthBuilderFn = (args: { dmk: DeviceManagementKit; sessionId: string }) =>\n | {\n withContextModule?(contextModule: ContextModule): { build(): ISdkSignerEth };\n build(): ISdkSignerEth;\n }\n | Promise<{\n withContextModule?(contextModule: ContextModule): { build(): ISdkSignerEth };\n build(): ISdkSignerEth;\n }>;\n\n/**\n * Per-sessionId SignerEth factory. Builds fresh on every call — DMK signers\n * hold DeviceAction state that isn't safe to reuse, so `invalidate` /\n * `clearAll` are kept as no-op lifecycle hooks for callers.\n */\nexport class SignerManager {\n private readonly _dmk: DeviceManagementKit;\n\n private readonly _builderFn: SignerEthBuilderFn;\n\n constructor(dmk: DeviceManagementKit, builderFn?: SignerEthBuilderFn) {\n this._dmk = dmk;\n this._builderFn = builderFn ?? SignerManager._defaultBuilder();\n }\n\n async getOrCreate(sessionId: string): Promise<SignerEth> {\n debugLog('[DMK] SignerManager.getOrCreate:', { sessionId });\n const builder = await this._builderFn({ dmk: this._dmk, sessionId });\n const builderWithContext = builder.withContextModule\n ? builder.withContextModule(SignerManager._createContextModule())\n : builder;\n return new SignerEth(builderWithContext.build());\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars, class-methods-use-this\n invalidate(_sessionId: string): void {}\n\n // eslint-disable-next-line class-methods-use-this\n clearAll(): void {}\n\n private static _defaultBuilder(): SignerEthBuilderFn {\n return args => new SignerEthBuilder(args);\n }\n\n private static _createContextModule(): ContextModule {\n const contextModule = new ContextModuleBuilder({}).removeDefaultLoaders().build();\n return SignerManager.wrapBlindSigningReportNonBlocking(contextModule);\n }\n\n static wrapBlindSigningReportNonBlocking<T extends ContextModule>(contextModule: T): T {\n const report = contextModule.report.bind(contextModule);\n contextModule.report = async params => {\n try {\n void report(params).catch(err => {\n debugLog('[DMK] ContextModule.report failed:', err);\n });\n } catch (err) {\n debugLog('[DMK] ContextModule.report failed:', err);\n }\n };\n return contextModule;\n }\n}\n","import { hexToBytes } from '@onekeyfe/hwk-adapter-core';\n\nimport { deviceActionToPromise } from './deviceActionToPromise';\nimport { debugLog } from '../utils/debugLog';\n\nimport type { CancelReason } from './deviceActionToPromise';\nimport type { SignerEth as ISdkSignerEth, TypedData } from '@ledgerhq/device-signer-kit-ethereum';\nimport type { SignerEvmAddress, SignerEvmSignature } from '../types';\n\n/** Timeout for user-interactive operations (verify address, sign). */\nconst INTERACTIVE_TIMEOUT_MS = 5 * 60_000;\n\n/**\n * Wraps Ledger's SDK signer (Observable-based DeviceActions) into\n * a simple async interface returning plain serializable data.\n */\nexport class SignerEth {\n onInteraction?: (interaction: string) => void;\n\n // eslint-disable-next-line no-useless-constructor, no-empty-function\n constructor(private readonly _sdk: ISdkSignerEth) {}\n\n /**\n * Optional callback registered per-call so the caller can obtain a canceller\n * for the underlying DeviceAction. Caller can invoke it to release DMK's\n * IntentQueue slot and unsubscribe from the action's observable.\n */\n onRegisterCanceller?: (cancel: (reason?: CancelReason) => void) => void;\n\n async getAddress(\n derivationPath: string,\n options?: { checkOnDevice?: boolean }\n ): Promise<SignerEvmAddress> {\n const checkOnDevice = options?.checkOnDevice ?? false;\n debugLog('[DMK] getAddress → DMK:', { derivationPath, checkOnDevice });\n const action = this._sdk.getAddress(derivationPath, {\n checkOnDevice,\n });\n // checkOnDevice needs user interaction → long timeout; otherwise default 30s\n const timeout = checkOnDevice ? INTERACTIVE_TIMEOUT_MS : undefined;\n return deviceActionToPromise<SignerEvmAddress>(\n action,\n this.onInteraction,\n timeout,\n this.onRegisterCanceller\n );\n }\n\n async signTransaction(\n derivationPath: string,\n serializedTxHex: string\n ): Promise<SignerEvmSignature> {\n const action = this._sdk.signTransaction(derivationPath, hexToBytes(serializedTxHex));\n return deviceActionToPromise<SignerEvmSignature>(\n action,\n this.onInteraction,\n INTERACTIVE_TIMEOUT_MS,\n this.onRegisterCanceller\n );\n }\n\n async signMessage(derivationPath: string, message: string): Promise<SignerEvmSignature> {\n // DMK treats string as ASCII text (addAsciiStringToData), but we receive\n // hex-encoded message bytes. Decode to Uint8Array so DMK uses\n // addBufferToData — matching the OneKey SDK's behavior.\n const action = this._sdk.signMessage(derivationPath, hexToBytes(message));\n return deviceActionToPromise<SignerEvmSignature>(\n action,\n this.onInteraction,\n INTERACTIVE_TIMEOUT_MS,\n this.onRegisterCanceller\n );\n }\n\n async signTypedData(derivationPath: string, data: TypedData): Promise<SignerEvmSignature> {\n const action = this._sdk.signTypedData(derivationPath, data);\n return deviceActionToPromise<SignerEvmSignature>(\n action,\n this.onInteraction,\n INTERACTIVE_TIMEOUT_MS,\n this.onRegisterCanceller\n );\n }\n}\n","import { DeviceActionStatus } from '@ledgerhq/device-management-kit';\n\nimport { debugLog } from '../utils/debugLog';\n\nimport type { DeviceAction, DeviceActionState } from '../types';\n\n/**\n * Idle watchdog: fires iff transport wedged (no DMK emission).\n * 65s > DMK's own 60s waitForDeviceUnlock — DMK fires first in normal\n * cases; we only catch the case where DMK itself is stuck.\n * Paused during interactive pending.\n */\nconst IDLE_WATCHDOG_MS = 65_000;\n\n/** Optional context attached to the rejection when a canceller fires. */\nexport interface CancelReason {\n code?: number;\n tag?: string;\n message?: string;\n}\n\n/**\n * Convert a DMK DeviceAction (Observable-based) into a Promise.\n * Handles pending -> completed/error state transitions and interaction callbacks.\n *\n * Tracks the last DMK step observed (e.g. `signer.eth.steps.blindSignTransactionFallback`)\n * and attaches it to the rejected error as a non-enumerable `_lastStep` property,\n * so upstream error classifiers can distinguish failure contexts (e.g. Blind signing\n * disabled vs. generic Invalid data).\n *\n * @param timeoutMs Idle watchdog ms. Re-armed on each emission, paused\n * during interactive pending. 0 disables. Default 65s\n * (covers DMK's 60s + margin; we're a backstop only).\n * @param onRegisterCanceller Optional callback that receives a function which, when\n * called, unsubscribes and cancels the underlying DeviceAction\n * (releases DMK's IntentQueue slot). Caller is responsible\n * for invoking the canceller on timeout/abort scenarios.\n */\nexport function deviceActionToPromise<T>(\n action: DeviceAction<T>,\n onInteraction?: (interaction: string) => void,\n timeoutMs: number = IDLE_WATCHDOG_MS,\n onRegisterCanceller?: (cancel: (reason?: CancelReason) => void) => void,\n onIntermediate?: (intermediateValue: unknown) => void\n): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n let settled = false;\n let lastStep: string | undefined;\n let activeInteraction: string | undefined;\n const observedSteps: string[] = [];\n // eslint-disable-next-line prefer-const -- assigned once after declaration, but must be declared before use in cleanup\n let sub: { unsubscribe: () => void };\n let timer: ReturnType<typeof setTimeout> | null = null;\n\n /** Fully tear down this action: unsubscribe + release DMK intent queue slot. */\n const cancelAction = () => {\n try {\n sub?.unsubscribe();\n } catch {\n // Subscription may already be closed.\n }\n try {\n action.cancel();\n } catch {\n // DMK action may already be settled.\n }\n };\n\n const clearActiveInteraction = () => {\n if (activeInteraction) {\n debugLog(\n '[DeviceAction] requiredUserInteraction',\n 'interaction=none',\n `prev=${activeInteraction}`,\n `step=${lastStep ?? 'unknown'}`\n );\n activeInteraction = undefined;\n onInteraction?.('interaction-complete');\n return true;\n }\n return false;\n };\n\n const emitInteraction = (interaction: unknown) => {\n if (!onInteraction) {\n return;\n }\n\n if (!interaction || interaction === 'none') {\n clearActiveInteraction();\n return;\n }\n\n const interactionName = String(interaction);\n if (interactionName === activeInteraction) {\n return;\n }\n\n activeInteraction = interactionName;\n debugLog(\n '[DeviceAction] requiredUserInteraction',\n `interaction=${interactionName}`,\n `step=${lastStep ?? 'unknown'}`\n );\n // unlock-device is DMK's own bounded poll. Other interaction\n // states keep the caller-provided watchdog so a stuck observable\n // cannot hold the queue slot forever.\n if (interaction === 'unlock-device' && timer) {\n clearTimeout(timer);\n timer = null;\n }\n onInteraction(interactionName);\n };\n\n const completeInteraction = () => {\n if (!clearActiveInteraction()) {\n onInteraction?.('interaction-complete');\n }\n };\n\n const armIdleWatchdog = () => {\n if (timer) clearTimeout(timer);\n if (timeoutMs > 0) {\n timer = setTimeout(() => {\n if (!settled) {\n settled = true;\n completeInteraction();\n cancelAction();\n reject(\n new Error(\n 'Ledger transport unresponsive: no DMK state change within the watchdog window. The device may have lost connection.'\n )\n );\n }\n }, timeoutMs);\n }\n };\n\n armIdleWatchdog();\n\n // Expose a canceller for external abort. Optional reason tags the rejection.\n if (onRegisterCanceller) {\n onRegisterCanceller(reason => {\n if (settled) {\n return;\n }\n settled = true;\n if (timer) clearTimeout(timer);\n completeInteraction();\n cancelAction();\n const err = new Error(reason?.message ?? 'Device action cancelled');\n if (reason?.code !== undefined) {\n (err as Error & { code?: number }).code = reason.code;\n }\n if (reason?.tag) {\n Object.defineProperty(err, '_tag', {\n value: reason.tag,\n configurable: true,\n enumerable: false,\n writable: true,\n });\n }\n reject(err);\n });\n }\n\n sub = action.observable.subscribe({\n next: (state: DeviceActionState<T>) => {\n // Drop post-settle emissions to avoid leaking the watchdog.\n if (settled) {\n return;\n }\n armIdleWatchdog();\n\n // Track last DMK step so caller can disambiguate failure contexts\n // (e.g. 0x6a80 during blindSignTransactionFallback = Blind signing disabled)\n const step = (state as { intermediateValue?: { step?: string } })?.intermediateValue?.step;\n if (step) {\n lastStep = step;\n if (observedSteps[observedSteps.length - 1] !== step) {\n observedSteps.push(step);\n }\n }\n\n if (state.status === DeviceActionStatus.Completed) {\n settled = true;\n if (timer) clearTimeout(timer);\n completeInteraction();\n sub?.unsubscribe();\n resolve(state.output);\n } else if (state.status === DeviceActionStatus.Error) {\n settled = true;\n if (timer) clearTimeout(timer);\n completeInteraction();\n sub?.unsubscribe();\n rejectWithStepContext(state.error, lastStep, observedSteps, reject);\n } else if (state.status === DeviceActionStatus.Pending) {\n if (onIntermediate) {\n try {\n onIntermediate(state.intermediateValue);\n } catch {\n // listener errors must not abort the device action\n }\n }\n if (onInteraction) {\n const interaction = state.intermediateValue?.requiredUserInteraction;\n emitInteraction(interaction);\n }\n }\n },\n error: (err: unknown) => {\n if (!settled) {\n settled = true;\n if (timer) clearTimeout(timer);\n completeInteraction();\n sub?.unsubscribe();\n rejectWithStepContext(err, lastStep, observedSteps, reject);\n }\n },\n complete: () => {\n if (!settled) {\n settled = true;\n if (timer) clearTimeout(timer);\n completeInteraction();\n reject(new Error('Device action completed without result'));\n }\n },\n });\n });\n}\n\n/**\n * Reject with the DMK error after annotating observed step context. These\n * fields are non-enumerable so they do not pollute JSON.stringify / log\n * output, but classifiers can still read them.\n */\nfunction rejectWithStepContext(\n err: unknown,\n lastStep: string | undefined,\n observedSteps: string[],\n reject: (reason: unknown) => void\n): void {\n if (err && typeof err === 'object' && (lastStep || observedSteps.length > 0)) {\n try {\n if (lastStep) {\n Object.defineProperty(err, '_lastStep', {\n value: lastStep,\n configurable: true,\n enumerable: false,\n writable: true,\n });\n }\n if (observedSteps.length > 0) {\n Object.defineProperty(err, '_deviceActionSteps', {\n value: [...observedSteps],\n configurable: true,\n enumerable: false,\n writable: true,\n });\n }\n } catch {\n // Frozen error objects — give up, classifier will fall back.\n }\n }\n reject(err);\n}\n","import { HardwareErrorCode, padHex64, stripHex } from '@onekeyfe/hwk-adapter-core';\n\nimport { collapseSignerInteraction, normalizePath } from './utils';\nimport { debugLog } from '../../utils/debugLog';\n\nimport type { TypedData } from '@ledgerhq/device-signer-kit-ethereum';\nimport type { SignerEvmSignature } from '../../types';\nimport type { ConnectorContext } from './types';\n\n// ---------------------------------------------------------------------------\n// Call param types\n// ---------------------------------------------------------------------------\n\nexport interface EvmGetAddressCallParams {\n path: string;\n showOnDevice?: boolean;\n}\n\nexport interface EvmSignTransactionCallParams {\n path: string;\n /** RLP-serialized transaction hex (0x-prefixed or plain) */\n serializedTx?: string;\n}\n\nexport interface EvmSignMessageCallParams {\n path: string;\n message: string;\n}\n\nexport interface EvmSignTypedDataCallParams {\n path: string;\n data: TypedData;\n mode?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Handler\n// ---------------------------------------------------------------------------\n\nexport async function evmGetAddress(\n ctx: ConnectorContext,\n sessionId: string,\n params: EvmGetAddressCallParams\n): Promise<{ address: string; publicKey?: string }> {\n const signer = await _getEthSigner(ctx, sessionId);\n const path = normalizePath(params.path);\n const checkOnDevice = params.showOnDevice ?? false;\n debugLog('[DMK] evmGetAddress -> signer.getAddress:', { path, checkOnDevice });\n\n try {\n const result = await signer.getAddress(path, { checkOnDevice });\n return { address: result.address, publicKey: result.publicKey };\n } catch (err) {\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err);\n } finally {\n ctx.clearCanceller(sessionId);\n }\n}\n\nexport async function evmSignTransaction(\n ctx: ConnectorContext,\n sessionId: string,\n params: EvmSignTransactionCallParams\n): Promise<{ v: string; r: string; s: string }> {\n if (!params.serializedTx) {\n throw Object.assign(\n new Error(\n 'Ledger requires a pre-serialized transaction (serializedTx). Provide an RLP-encoded hex string.'\n ),\n { code: HardwareErrorCode.InvalidParams }\n );\n }\n\n const signer = await _getEthSigner(ctx, sessionId);\n const path = normalizePath(params.path);\n\n try {\n const result: SignerEvmSignature = await signer.signTransaction(path, params.serializedTx);\n return {\n v: `0x${result.v.toString(16)}`,\n r: padHex64(result.r),\n s: padHex64(result.s),\n };\n } catch (err) {\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err);\n } finally {\n ctx.clearCanceller(sessionId);\n }\n}\n\nexport async function evmSignMessage(\n ctx: ConnectorContext,\n sessionId: string,\n params: EvmSignMessageCallParams\n): Promise<{ signature: string }> {\n const signer = await _getEthSigner(ctx, sessionId);\n const path = normalizePath(params.path);\n\n try {\n const result: SignerEvmSignature = await signer.signMessage(path, params.message);\n const rHex = stripHex(result.r).padStart(64, '0');\n const sHex = stripHex(result.s).padStart(64, '0');\n const vHex = result.v.toString(16).padStart(2, '0');\n return { signature: `0x${rHex}${sHex}${vHex}` };\n } catch (err) {\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err);\n } finally {\n ctx.clearCanceller(sessionId);\n }\n}\n\nexport async function evmSignTypedData(\n ctx: ConnectorContext,\n sessionId: string,\n params: EvmSignTypedDataCallParams\n): Promise<{ signature: string }> {\n if (params.mode === 'hash') {\n throw Object.assign(\n new Error(\n 'Ledger does not support hash-only EIP-712 signing. Use mode \"full\" with the complete typed data structure.'\n ),\n { code: HardwareErrorCode.MethodNotSupported }\n );\n }\n\n const signer = await _getEthSigner(ctx, sessionId);\n const path = normalizePath(params.path);\n\n try {\n const result: SignerEvmSignature = await signer.signTypedData(path, params.data);\n const rHex = stripHex(result.r).padStart(64, '0');\n const sHex = stripHex(result.s).padStart(64, '0');\n const vHex = result.v.toString(16).padStart(2, '0');\n return { signature: `0x${rHex}${sHex}${vHex}` };\n } catch (err) {\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err);\n } finally {\n ctx.clearCanceller(sessionId);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Internal — ETH signer creation\n// ---------------------------------------------------------------------------\n\nasync function _getEthSigner(ctx: ConnectorContext, sessionId: string) {\n const signerManager = await ctx.getSignerManager();\n const signer = await signerManager.getOrCreate(sessionId);\n\n // Wire up interaction events (open-app, unlock, verify-address, sign, etc.)\n // DMK-specific values (verify-address, sign-transaction, sign-typed-data,\n // sign-personal-message) collapse to ConfirmOnDevice via the helper.\n signer.onInteraction = (interaction: string) => {\n debugLog('[LedgerConnector] evm.onInteraction:', interaction);\n ctx.emit('ui-event', {\n type: collapseSignerInteraction(interaction),\n payload: { sessionId },\n });\n };\n\n // Expose DeviceAction canceller to the connector so that cancel(sessionId)\n // can release DMK's intent queue slot and unsubscribe cleanly.\n signer.onRegisterCanceller = cancel => {\n ctx.registerCanceller(sessionId, cancel);\n };\n\n return signer;\n}\n","import { EConnectorInteraction } from '@onekeyfe/hwk-adapter-core';\n\n/**\n * Strip the \"m/\" prefix from BIP-44 derivation paths.\n * Ledger DMK requires paths without the \"m/\" prefix.\n */\nexport function normalizePath(path: string): string {\n return path.startsWith('m/') ? path.slice(2) : path;\n}\n\n/**\n * Collapse Ledger DMK's raw `requiredUserInteraction` strings into the\n * subset of EConnectorInteraction variants that share the simple\n * `{ sessionId }` payload shape — used by chain-signer emit sites.\n *\n * DMK emits chain-signer-specific strings like \"verify-address\",\n * \"sign-transaction\", \"sign-typed-data\", \"sign-personal-message\" — they\n * all mean \"the user must act on the device screen\", i.e. ConfirmOnDevice\n * per the public ConnectorUiEvent type contract. Leaking raw DMK strings\n * out of the SDK would break consumers that switch on EConnectorInteraction.\n *\n * Note: AppInstallProgress and Searching are NOT in the return type — they\n * carry richer payloads and are emitted from dedicated call sites.\n */\nexport type CollapsedSignerInteraction =\n | EConnectorInteraction.ConfirmOpenApp\n | EConnectorInteraction.UnlockDevice\n | EConnectorInteraction.InteractionComplete\n | EConnectorInteraction.ConfirmOnDevice;\n\nexport function collapseSignerInteraction(interaction: string): CollapsedSignerInteraction {\n switch (interaction) {\n case 'confirm-open-app':\n return EConnectorInteraction.ConfirmOpenApp;\n case 'unlock-device':\n return EConnectorInteraction.UnlockDevice;\n case 'interaction-complete':\n return EConnectorInteraction.InteractionComplete;\n default:\n return EConnectorInteraction.ConfirmOnDevice;\n }\n}\n","import { HardwareErrorCode, stripHex } from '@onekeyfe/hwk-adapter-core';\nimport { Psbt } from 'bitcoinjs-lib';\n\nimport { collapseSignerInteraction, normalizePath } from './utils';\nimport { SignerBtc } from '../../signer/SignerBtc';\nimport { debugError, debugLog } from '../../utils/debugLog';\n\nimport type { ConnectorContext } from './types';\n\n// ---------------------------------------------------------------------------\n// Call param types\n// ---------------------------------------------------------------------------\n\nexport interface BtcGetAddressCallParams {\n /** Account-level derivation path (3 levels, e.g. \"m/86'/0'/0'\") */\n path: string;\n showOnDevice?: boolean;\n /** Address index within the account (default: 0) */\n addressIndex?: number;\n /** Whether this is a change address (default: false) */\n change?: boolean;\n}\n\nexport interface BtcGetPublicKeyCallParams {\n path: string;\n showOnDevice?: boolean;\n}\n\nexport interface BtcSignTransactionCallParams {\n psbt?: string;\n coin: string;\n /** Account-level derivation path for wallet template determination (e.g. \"84'/0'/0'\"). */\n path?: string;\n}\n\nexport interface BtcSignPsbtCallParams {\n psbt: string;\n coin?: string;\n path?: string;\n}\n\nexport interface BtcSignMessageCallParams {\n path: string;\n message: string;\n coin?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Internal -- BIP-44 purpose → Ledger wallet template\n// ---------------------------------------------------------------------------\n\n/**\n * BIP-44 purpose → Ledger descriptor template. Throws on unknown —\n * silent NATIVE_SEGWIT fallback would yield wrong addresses for\n * multisig (m/48') / legacy BIP-45 accounts. DDT is injected because\n * it comes from a runtime `importLedgerKit`.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction _purposeToTemplate(purpose: string | undefined, DDT: any): any {\n switch (purpose) {\n case '44':\n return DDT.LEGACY;\n case '49':\n return DDT.NESTED_SEGWIT;\n case '84':\n return DDT.NATIVE_SEGWIT;\n case '86':\n return DDT.TAPROOT;\n default:\n throw Object.assign(new Error(`Unsupported BTC purpose: m/${purpose ?? '<undefined>'}'`), {\n code: HardwareErrorCode.InvalidParams,\n });\n }\n}\n\n// ---------------------------------------------------------------------------\n// Handlers\n// ---------------------------------------------------------------------------\n\nexport async function btcGetAddress(\n ctx: ConnectorContext,\n sessionId: string,\n params: BtcGetAddressCallParams\n): Promise<{ address: string; path: string }> {\n const btcSigner = await _createBtcSigner(ctx, sessionId);\n const path = normalizePath(params.path);\n\n try {\n const { DefaultWallet, DefaultDescriptorTemplate } = await ctx.importLedgerKit(\n '@ledgerhq/device-signer-kit-bitcoin'\n );\n const purpose = path.split('/')[0]?.replace(/'/g, '');\n const template = _purposeToTemplate(purpose, DefaultDescriptorTemplate);\n const wallet = new DefaultWallet(path, template);\n\n debugLog('[LedgerConnector] btcGetAddress params:', {\n path,\n purpose,\n template,\n addressIndex: params.addressIndex,\n change: params.change,\n showOnDevice: params.showOnDevice,\n });\n\n const result = await btcSigner.getWalletAddress(wallet, params.addressIndex ?? 0, {\n checkOnDevice: params.showOnDevice ?? false,\n change: params.change ?? false,\n });\n return { address: result.address, path: params.path };\n } catch (err) {\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err);\n } finally {\n ctx.clearCanceller(sessionId);\n }\n}\n\nexport async function btcGetPublicKey(\n ctx: ConnectorContext,\n sessionId: string,\n params: BtcGetPublicKeyCallParams\n): Promise<{ xpub: string; path: string }> {\n const btcSigner = await _createBtcSigner(ctx, sessionId);\n const path = normalizePath(params.path);\n\n debugLog('[LedgerConnector] btcGetPublicKey called, path:', path, 'sessionId:', sessionId);\n try {\n const xpub = await btcSigner.getExtendedPublicKey(path, {\n checkOnDevice: params.showOnDevice ?? false,\n });\n debugLog('[LedgerConnector] btcGetPublicKey success, xpub:', `${xpub?.substring(0, 20)}...`);\n return { xpub, path: params.path };\n } catch (err) {\n debugError('[LedgerConnector] btcGetPublicKey error, path:', path, 'err:', err);\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err);\n } finally {\n ctx.clearCanceller(sessionId);\n }\n}\n\nexport async function btcSignTransaction(\n ctx: ConnectorContext,\n sessionId: string,\n params: BtcSignTransactionCallParams\n): Promise<{ serializedTx: string }> {\n if (!params.psbt) {\n throw Object.assign(\n new Error('Ledger requires PSBT format for BTC transaction signing. Provide params.psbt.'),\n { code: HardwareErrorCode.InvalidParams }\n );\n }\n\n const btcSigner = await _createBtcSigner(ctx, sessionId);\n\n try {\n const { DefaultWallet, DefaultDescriptorTemplate } = await ctx.importLedgerKit(\n '@ledgerhq/device-signer-kit-bitcoin'\n );\n\n // Determine wallet template from the account-level derivation path\n const path = normalizePath(params.path || \"84'/0'/0'\");\n const purpose = path.split('/')[0]?.replace(/'/g, '');\n const template = _purposeToTemplate(purpose, DefaultDescriptorTemplate);\n debugLog('[LedgerConnector] btcSignTransaction wallet:', { path, purpose, template });\n\n const wallet = new DefaultWallet(path, template);\n\n const signedTxHex = await btcSigner.signTransaction(wallet, params.psbt);\n\n return { serializedTx: stripHex(signedTxHex) };\n } catch (err) {\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err);\n } finally {\n ctx.clearCanceller(sessionId);\n }\n}\n\nexport async function btcSignPsbt(\n ctx: ConnectorContext,\n sessionId: string,\n params: BtcSignPsbtCallParams\n): Promise<{ signedPsbt: string }> {\n if (!params.psbt) {\n throw Object.assign(new Error('btcSignPsbt requires params.psbt'), {\n code: HardwareErrorCode.InvalidParams,\n });\n }\n\n const btcSigner = await _createBtcSigner(ctx, sessionId);\n\n try {\n const { DefaultWallet, DefaultDescriptorTemplate } = await ctx.importLedgerKit(\n '@ledgerhq/device-signer-kit-bitcoin'\n );\n\n const path = normalizePath(params.path || \"84'/0'/0'\");\n const purpose = path.split('/')[0]?.replace(/'/g, '');\n const template = _purposeToTemplate(purpose, DefaultDescriptorTemplate);\n debugLog('[LedgerConnector] btcSignPsbt wallet:', { path, purpose, template });\n\n const wallet = new DefaultWallet(path, template);\n\n const signatures = (await btcSigner.signPsbt(wallet, params.psbt)) as Array<{\n inputIndex: number;\n pubkey: Uint8Array;\n signature: Uint8Array;\n tapleafHash?: Uint8Array;\n }>;\n debugLog('[LedgerConnector] btcSignPsbt signatures received:', signatures.length);\n\n const signedPsbtHex = _applySignaturesToPsbt(params.psbt, signatures);\n return { signedPsbt: signedPsbtHex };\n } catch (err) {\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err);\n } finally {\n ctx.clearCanceller(sessionId);\n }\n}\n\nexport async function btcSignMessage(\n ctx: ConnectorContext,\n sessionId: string,\n params: BtcSignMessageCallParams\n): Promise<{ signature: string; address?: string }> {\n const btcSigner = await _createBtcSigner(ctx, sessionId);\n const path = normalizePath(params.path);\n\n try {\n // signMessage returns { r: HexaString, s: HexaString, v: number }\n const result = await btcSigner.signMessage(path, params.message);\n\n // BIP-137: signature = v(1) + r(32) + s(32); returned as hex (OneKey SDK style).\n const vHex = result.v.toString(16).padStart(2, '0');\n const rHex = stripHex(result.r).padStart(64, '0');\n const sHex = stripHex(result.s).padStart(64, '0');\n\n return { signature: `${vHex}${rHex}${sHex}` };\n } catch (err) {\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err);\n } finally {\n ctx.clearCanceller(sessionId);\n }\n}\n\nexport async function btcGetMasterFingerprint(\n ctx: ConnectorContext,\n sessionId: string,\n params?: { skipOpenApp?: boolean }\n): Promise<{ masterFingerprint: string }> {\n const btcSigner = await _createBtcSigner(ctx, sessionId);\n\n try {\n const fingerprint: Uint8Array = await btcSigner.getMasterFingerprint({\n skipOpenApp: params?.skipOpenApp,\n });\n // Convert Uint8Array to hex string\n const hex = Array.from(fingerprint)\n .map(b => b.toString(16).padStart(2, '0'))\n .join('');\n return { masterFingerprint: hex };\n } catch (err) {\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err);\n } finally {\n ctx.clearCanceller(sessionId);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Internal -- BTC signer creation\n// ---------------------------------------------------------------------------\n\nasync function _createBtcSigner(ctx: ConnectorContext, sessionId: string): Promise<SignerBtc> {\n const dmk = await ctx.getOrCreateDmk();\n const { SignerBtcBuilder } = await ctx.importLedgerKit('@ledgerhq/device-signer-kit-bitcoin');\n const sdkSigner = new SignerBtcBuilder({ dmk, sessionId }).build();\n const signer = new SignerBtc(sdkSigner);\n\n // Wire up interaction events (open-app, unlock, sign, etc.)\n // DMK-specific values (sign-transaction, sign-personal-message,\n // verify-address) collapse to ConfirmOnDevice via the helper.\n signer.onInteraction = (interaction: string) => {\n debugLog('[LedgerConnector] btc.onInteraction:', interaction);\n ctx.emit('ui-event', {\n type: collapseSignerInteraction(interaction),\n payload: { sessionId },\n });\n };\n\n signer.onRegisterCanceller = cancel => {\n ctx.registerCanceller(sessionId, cancel);\n };\n\n return signer;\n}\n\n// ---------------------------------------------------------------------------\n// Internal -- Apply partial signatures to PSBT\n// ---------------------------------------------------------------------------\n\ntype PsbtInput = Psbt['data']['inputs'][number];\n\nfunction _isTaprootInput(input: PsbtInput): boolean {\n if (\n input.tapInternalKey ||\n input.tapKeySig ||\n input.tapLeafScript ||\n input.tapMerkleRoot ||\n input.tapBip32Derivation ||\n input.tapScriptSig\n )\n return true;\n // P2TR scriptPubKey: OP_1 (0x51) + PUSH32 (0x20) + <32B x-only>\n const script = input.witnessUtxo?.script;\n return !!(script && script.length === 34 && script[0] === 0x51 && script[1] === 0x20);\n}\n\nfunction _isScriptPathInput(input: PsbtInput): boolean {\n return !!(input.tapLeafScript && input.tapLeafScript.length > 0);\n}\n\n/**\n * Dispatch DMK-returned signatures to the correct PSBT field using the\n * input's scriptPubKey as authoritative signal; throws on shape violations.\n */\nexport function _applySignaturesToPsbt(\n psbtHex: string,\n signatures: Array<{\n inputIndex: number;\n pubkey: Uint8Array;\n signature: Uint8Array;\n tapleafHash?: Uint8Array;\n }>\n): string {\n const psbt = Psbt.fromHex(psbtHex);\n for (const sig of signatures) {\n const input = psbt.data.inputs[sig.inputIndex];\n if (!input) {\n throw new Error(`_applySignaturesToPsbt: no PSBT input at index ${sig.inputIndex}`);\n }\n const taproot = _isTaprootInput(input);\n const scriptPath = taproot && _isScriptPathInput(input);\n const hasLeafHash = !!(sig.tapleafHash && sig.tapleafHash.length > 0);\n\n if (scriptPath) {\n if (sig.pubkey.length !== 32)\n throw new Error(\n `input ${sig.inputIndex}: taproot script-path pubkey must be 32B, got ${sig.pubkey.length}`\n );\n if (!hasLeafHash)\n throw new Error(\n `input ${sig.inputIndex}: taproot script-path signature missing tapleafHash`\n );\n psbt.updateInput(sig.inputIndex, {\n tapScriptSig: [\n { pubkey: sig.pubkey, leafHash: sig.tapleafHash!, signature: sig.signature },\n ],\n });\n } else if (taproot) {\n if (sig.pubkey.length !== 32)\n throw new Error(\n `input ${sig.inputIndex}: taproot key-path pubkey must be 32B, got ${sig.pubkey.length}`\n );\n if (hasLeafHash)\n throw new Error(\n `input ${sig.inputIndex}: taproot key-path signature must not carry tapleafHash`\n );\n psbt.updateInput(sig.inputIndex, { tapKeySig: sig.signature });\n } else {\n if (sig.pubkey.length !== 33 && sig.pubkey.length !== 65)\n throw new Error(\n `input ${sig.inputIndex}: ECDSA pubkey must be 33B or 65B, got ${sig.pubkey.length}`\n );\n if (hasLeafHash)\n throw new Error(`input ${sig.inputIndex}: ECDSA signature must not carry tapleafHash`);\n psbt.updateInput(sig.inputIndex, {\n partialSig: [{ pubkey: sig.pubkey, signature: sig.signature }],\n });\n }\n }\n return psbt.toHex();\n}\n","import { hexToBytes } from '@onekeyfe/hwk-adapter-core';\n\nimport { deviceActionToPromise } from './deviceActionToPromise';\nimport { debugError, debugLog } from '../utils/debugLog';\n\nimport type { CancelReason } from './deviceActionToPromise';\nimport type { SignerBtc as ISdkSignerBtc } from '@ledgerhq/device-signer-kit-bitcoin';\nimport type { SignerBtcAddress } from '../types';\n\n// Extract parameter types from the real SignerBtc interface to avoid deep path imports.\ntype BtcWallet = Parameters<ISdkSignerBtc['getWalletAddress']>[0];\ntype BtcPsbt = Parameters<ISdkSignerBtc['signPsbt']>[1];\ntype BtcPsbtOptions = Parameters<ISdkSignerBtc['signPsbt']>[2];\ntype BtcMessageOptions = Parameters<ISdkSignerBtc['signMessage']>[2];\n\n/** Decode hex string (with or without 0x prefix) to UTF-8 text. */\nfunction hexToUtf8(hex: string): string {\n return new TextDecoder().decode(hexToBytes(hex));\n}\n\n/** Timeout for user-interactive operations (sign, verify). */\nconst INTERACTIVE_TIMEOUT_MS = 5 * 60_000;\n\n/**\n * Wraps Ledger's BTC SDK signer (Observable-based DeviceActions) into\n * a simple async interface returning plain serializable data.\n */\nexport class SignerBtc {\n onInteraction?: (interaction: string) => void;\n\n onRegisterCanceller?: (cancel: (reason?: CancelReason) => void) => void;\n\n // eslint-disable-next-line no-useless-constructor, no-empty-function\n constructor(private readonly _sdk: ISdkSignerBtc) {}\n\n async getWalletAddress(\n wallet: BtcWallet,\n addressIndex: number,\n options?: { checkOnDevice?: boolean; change?: boolean }\n ): Promise<SignerBtcAddress> {\n const action = this._sdk.getWalletAddress(wallet, addressIndex, {\n checkOnDevice: options?.checkOnDevice ?? false,\n change: options?.change ?? false,\n });\n return deviceActionToPromise<SignerBtcAddress>(\n action,\n this.onInteraction,\n undefined,\n this.onRegisterCanceller\n );\n }\n\n async getExtendedPublicKey(\n derivationPath: string,\n options?: { checkOnDevice?: boolean }\n ): Promise<string> {\n debugLog(\n '[SignerBtc] getExtendedPublicKey called, path:',\n derivationPath,\n 'options:',\n JSON.stringify(options)\n );\n const action = this._sdk.getExtendedPublicKey(derivationPath, {\n checkOnDevice: options?.checkOnDevice ?? false,\n });\n try {\n // DMK returns { extendedPublicKey: string }, unwrap it\n const result = await deviceActionToPromise<string | { extendedPublicKey: string }>(\n action,\n this.onInteraction,\n undefined,\n this.onRegisterCanceller\n );\n debugLog(\n '[SignerBtc] getExtendedPublicKey result type:',\n typeof result,\n 'value:',\n typeof result === 'string'\n ? `${result.substring(0, 20)}...`\n : JSON.stringify(result).substring(0, 50)\n );\n if (typeof result === 'string') return result;\n return result.extendedPublicKey;\n } catch (err) {\n debugError('[SignerBtc] getExtendedPublicKey error:', err);\n throw err;\n }\n }\n\n async getMasterFingerprint(options?: { skipOpenApp?: boolean }): Promise<Uint8Array> {\n const action = this._sdk.getMasterFingerprint(options);\n const result = await deviceActionToPromise<{ masterFingerprint: Uint8Array }>(\n action,\n this.onInteraction,\n undefined,\n this.onRegisterCanceller\n );\n return result.masterFingerprint;\n }\n\n /**\n * Sign a PSBT and return the array of partial signatures.\n * The `wallet` param is a DefaultWallet or WalletPolicy instance.\n * The `psbt` param can be a hex string, base64 string, or Uint8Array.\n */\n async signPsbt(wallet: BtcWallet, psbt: BtcPsbt, options?: BtcPsbtOptions): Promise<unknown[]> {\n const action = this._sdk.signPsbt(wallet, psbt, options);\n return deviceActionToPromise<unknown[]>(\n action,\n this.onInteraction,\n INTERACTIVE_TIMEOUT_MS,\n this.onRegisterCanceller\n );\n }\n\n /**\n * Sign a PSBT and return the fully extracted raw transaction as a hex string.\n * Like signPsbt, but also finalises the PSBT and extracts the transaction.\n */\n async signTransaction(\n wallet: BtcWallet,\n psbt: BtcPsbt,\n options?: BtcPsbtOptions\n ): Promise<string> {\n const action = this._sdk.signTransaction(wallet, psbt, options);\n return deviceActionToPromise<string>(\n action,\n this.onInteraction,\n INTERACTIVE_TIMEOUT_MS,\n this.onRegisterCanceller\n );\n }\n\n /**\n * Sign a message with the BTC app (BIP-137 / \"Bitcoin Signed Message\").\n * Returns `{ r, s, v }` signature object.\n */\n async signMessage(\n derivationPath: string,\n message: string,\n options?: BtcMessageOptions\n ): Promise<{ r: string; s: string; v: number }> {\n // DMK uses TextEncoder to convert message string to bytes.\n // We receive hex-encoded message, so decode hex -> UTF-8 text first.\n const action = this._sdk.signMessage(derivationPath, hexToUtf8(message), options);\n return deviceActionToPromise<{ r: string; s: string; v: number }>(\n action,\n this.onInteraction,\n INTERACTIVE_TIMEOUT_MS,\n this.onRegisterCanceller\n );\n }\n}\n","import { bytesToHex, hexToBytes } from '@onekeyfe/hwk-adapter-core';\n\nimport { collapseSignerInteraction, normalizePath } from './utils';\nimport { SignerSol } from '../../signer/SignerSol';\nimport { debugLog } from '../../utils/debugLog';\n\nimport type { ConnectorContext } from './types';\n\n// ---------------------------------------------------------------------------\n// Call param types\n// ---------------------------------------------------------------------------\n\nexport interface SolGetAddressCallParams {\n path: string;\n showOnDevice?: boolean;\n}\n\nexport interface SolSignTransactionCallParams {\n path: string;\n /** Hex-encoded serialized transaction bytes (no 0x prefix) */\n serializedTx: string;\n}\n\nexport interface SolSignMessageCallParams {\n path: string;\n /** Message bytes as hex string (no 0x prefix) */\n message: string;\n}\n\n// ---------------------------------------------------------------------------\n// Handlers\n// ---------------------------------------------------------------------------\n\nexport async function solGetAddress(\n ctx: ConnectorContext,\n sessionId: string,\n params: SolGetAddressCallParams\n): Promise<{ address: string; path: string }> {\n const solSigner = await _createSolSigner(ctx, sessionId);\n const path = normalizePath(params.path);\n\n try {\n // Ledger Solana signer returns a base58-encoded Ed25519 public key (= Solana address)\n const publicKey = await solSigner.getAddress(path, {\n checkOnDevice: params.showOnDevice ?? false,\n });\n return { address: publicKey, path: params.path };\n } catch (err) {\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err);\n } finally {\n ctx.clearCanceller(sessionId);\n }\n}\n\nexport async function solSignTransaction(\n ctx: ConnectorContext,\n sessionId: string,\n params: SolSignTransactionCallParams\n): Promise<{ signature: string }> {\n const solSigner = await _createSolSigner(ctx, sessionId);\n const path = normalizePath(params.path);\n const txBytes = hexToBytes(params.serializedTx);\n\n try {\n const result = await solSigner.signTransaction(path, txBytes);\n return { signature: bytesToHex(result) };\n } catch (err) {\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err);\n } finally {\n ctx.clearCanceller(sessionId);\n }\n}\n\nexport async function solSignMessage(\n ctx: ConnectorContext,\n sessionId: string,\n params: SolSignMessageCallParams\n): Promise<{ signature: string }> {\n const solSigner = await _createSolSigner(ctx, sessionId);\n const path = normalizePath(params.path);\n const messageBytes = hexToBytes(params.message);\n\n try {\n // DMK signMessage returns { signature: string }, not raw Uint8Array\n const result = await solSigner.signMessage(path, messageBytes);\n return { signature: result.signature };\n } catch (err) {\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err);\n } finally {\n ctx.clearCanceller(sessionId);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Internal -- SOL signer creation\n// ---------------------------------------------------------------------------\n\nasync function _createSolSigner(ctx: ConnectorContext, sessionId: string): Promise<SignerSol> {\n const dmk = await ctx.getOrCreateDmk();\n const { ContextModuleBuilder } = await ctx.importLedgerKit('@ledgerhq/context-module');\n const { SignerSolanaBuilder } = await ctx.importLedgerKit('@ledgerhq/device-signer-kit-solana');\n const contextModule = new ContextModuleBuilder({}).removeDefaultLoaders().build();\n const sdkSigner = new SignerSolanaBuilder({ dmk, sessionId })\n .withContextModule(contextModule)\n .build();\n const signer = new SignerSol(sdkSigner);\n\n // Wire up interaction events (verify-address, sign, etc.)\n // DMK-specific values (verify-address, sign-transaction, sign-personal-message)\n // collapse to ConfirmOnDevice via the helper.\n signer.onInteraction = (interaction: string) => {\n debugLog('[LedgerConnector] sol.onInteraction:', interaction);\n ctx.emit('ui-event', {\n type: collapseSignerInteraction(interaction),\n payload: { sessionId },\n });\n };\n\n signer.onRegisterCanceller = cancel => {\n ctx.registerCanceller(sessionId, cancel);\n };\n\n return signer;\n}\n","import { deviceActionToPromise } from './deviceActionToPromise';\n\nimport type { CancelReason } from './deviceActionToPromise';\nimport type { SignerSolana as ISdkSignerSol } from '@ledgerhq/device-signer-kit-solana';\n\n// Extract parameter types from the real SignerSolana interface to avoid deep path imports.\ntype SolTxOptions = Parameters<ISdkSignerSol['signTransaction']>[2];\ntype SolMsgOptions = Parameters<ISdkSignerSol['signMessage']>[2];\n\n/**\n * Wraps Ledger's Solana SDK signer (Observable-based DeviceActions) into\n * a simple async interface returning plain serializable data.\n *\n * The Solana signer's `getAddress` returns a base58-encoded Ed25519 public key,\n * which is also the Solana address.\n */\nexport class SignerSol {\n onInteraction?: (interaction: string) => void;\n\n onRegisterCanceller?: (cancel: (reason?: CancelReason) => void) => void;\n\n // eslint-disable-next-line no-useless-constructor, no-empty-function\n constructor(private readonly _sdk: ISdkSignerSol) {}\n\n /**\n * Get the Solana address (base58-encoded Ed25519 public key) at the given derivation path.\n */\n async getAddress(derivationPath: string, options?: { checkOnDevice?: boolean }): Promise<string> {\n const action = this._sdk.getAddress(derivationPath, {\n checkOnDevice: options?.checkOnDevice ?? false,\n });\n return deviceActionToPromise<string>(\n action,\n this.onInteraction,\n undefined,\n this.onRegisterCanceller\n );\n }\n\n /**\n * Sign a Solana transaction.\n */\n async signTransaction(\n derivationPath: string,\n transaction: Uint8Array,\n options?: SolTxOptions\n ): Promise<Uint8Array> {\n const action = this._sdk.signTransaction(derivationPath, transaction, options);\n return deviceActionToPromise<Uint8Array>(\n action,\n this.onInteraction,\n undefined,\n this.onRegisterCanceller\n );\n }\n\n /**\n * Sign a message with the Solana app.\n * DMK returns { signature: string } for signMessage (unlike signTransaction which returns Uint8Array).\n */\n async signMessage(\n derivationPath: string,\n message: string | Uint8Array,\n options?: SolMsgOptions\n ): Promise<{ signature: string }> {\n const action = this._sdk.signMessage(derivationPath, message, options);\n return deviceActionToPromise<{ signature: string }>(\n action,\n this.onInteraction,\n undefined,\n this.onRegisterCanceller\n );\n }\n}\n","import { HardwareErrorCode } from '@onekeyfe/hwk-adapter-core';\nimport Trx from '@ledgerhq/hw-app-trx';\n\nimport { normalizePath } from './utils';\nimport { withLegacyChainCall } from './legacyChainCall';\nimport { DmkTransport } from '../../transport/DmkTransport';\n\nimport type { ConnectorContext } from './types';\n\n// ---------------------------------------------------------------------------\n// Call param types\n// ---------------------------------------------------------------------------\n\nexport interface TronGetAddressCallParams {\n path: string;\n showOnDevice?: boolean;\n}\n\nexport interface TronSignTransactionCallParams {\n path: string;\n /** Protobuf-encoded raw transaction hex (no 0x prefix) */\n rawTxHex: string;\n /**\n * TRC token metadata for Ledger clear-signing. Omit → TRC-20 transfers\n * fall back to blind-signing (user sees only raw bytes on-device).\n */\n tokenSignatures?: string[];\n}\n\nexport interface TronSignMessageCallParams {\n path: string;\n /** Message hex (no 0x prefix) */\n messageHex: string;\n}\n\n// ---------------------------------------------------------------------------\n// Handlers\n// ---------------------------------------------------------------------------\n\nexport async function tronGetAddress(\n ctx: ConnectorContext,\n sessionId: string,\n params: TronGetAddressCallParams\n): Promise<{ address: string; publicKey: string; path: string }> {\n const path = normalizePath(params.path);\n const showOnDevice = params.showOnDevice ?? false;\n\n return withLegacyChainCall(\n ctx,\n sessionId,\n {\n appName: 'Tron',\n // Only show \"confirm on device\" UI when the device is actually going\n // to display the address for the user to verify.\n needsConfirmation: showOnDevice,\n },\n async sid => {\n const trx = await _createTrx(ctx, sid);\n const result = await trx.getAddress(path, showOnDevice);\n return { address: result.address, publicKey: result.publicKey, path: params.path };\n }\n );\n}\n\nexport async function tronSignTransaction(\n ctx: ConnectorContext,\n sessionId: string,\n params: TronSignTransactionCallParams\n): Promise<{ signature: string }> {\n if (!params.rawTxHex) {\n throw Object.assign(\n new Error('TRON signing requires a protobuf-encoded raw transaction hex (rawTxHex).'),\n { code: HardwareErrorCode.InvalidParams }\n );\n }\n\n const path = normalizePath(params.path);\n\n return withLegacyChainCall(\n ctx,\n sessionId,\n { appName: 'Tron', needsConfirmation: true },\n async sid => {\n const trx = await _createTrx(ctx, sid);\n const signature = await trx.signTransaction(\n path,\n params.rawTxHex,\n params.tokenSignatures ?? []\n );\n return { signature };\n }\n );\n}\n\nexport async function tronSignMessage(\n ctx: ConnectorContext,\n sessionId: string,\n params: TronSignMessageCallParams\n): Promise<{ signature: string }> {\n const path = normalizePath(params.path);\n\n return withLegacyChainCall(\n ctx,\n sessionId,\n { appName: 'Tron', needsConfirmation: true },\n async sid => {\n const trx = await _createTrx(ctx, sid);\n const signature = await trx.signPersonalMessage(path, params.messageHex);\n return { signature };\n }\n );\n}\n\n// ---------------------------------------------------------------------------\n// Internal\n// ---------------------------------------------------------------------------\n\nasync function _createTrx(ctx: ConnectorContext, sessionId: string): Promise<Trx> {\n const dmk = await ctx.getOrCreateDmk();\n return new Trx(new DmkTransport(dmk, sessionId));\n}\n","import { EConnectorInteraction } from '@onekeyfe/hwk-adapter-core';\n\nimport { isWrongAppError } from '../../errors';\nimport { AppManager } from '../../app/AppManager';\nimport { debugLog } from '../../utils/debugLog';\n\nimport type { ConnectorContext } from './types';\n\nexport interface LegacyChainCallOptions {\n /** Target Ledger app name, e.g. 'Tron' / 'XRP' / 'Cardano'. */\n appName: string;\n /**\n * Whether the action triggers an on-device confirm prompt (sign, verify).\n * Controls the ConfirmOnDevice / InteractionComplete pair around `action`.\n * `false` for silent ops like getAddress(showOnDevice=false).\n */\n needsConfirmation: boolean;\n}\n\n/** `appName` reserved for future per-app extension. */\nexport function isLegacyWrongAppError(err: unknown, _appName: string): boolean {\n return isWrongAppError(err);\n}\n\n/**\n * Run a legacy-SDK device call (TRON et al. that lack `@ledgerhq/device-signer-kit-*`):\n * 1. ensureAppOpen pre-flight (legacy hw-app-* bypasses DMK DeviceAction).\n * 2. Emit ConfirmOnDevice when `needsConfirmation`.\n * 3. action().\n * 4. Always close any prompt with InteractionComplete (symmetric on success/failure).\n * 5. Retry once on wrong-app: re-ensure + clear signers + rerun action.\n */\nexport async function withLegacyChainCall<T>(\n ctx: ConnectorContext,\n sessionId: string,\n options: LegacyChainCallOptions,\n action: (sid: string) => Promise<T>\n): Promise<T> {\n const { appName, needsConfirmation } = options;\n\n // wrapError calls below pass `{ defaultAppName: appName }` explicitly even\n // though LedgerConnectorBase.dispatcher already injects it via _ctxForMethod.\n // Reason: this utility receives `appName` as an own parameter — it is the\n // source of truth for which app it's calling, so it must not silently rely\n // on whatever wrapError happens to be on the ctx passed in. If a future\n // caller invokes withLegacyChainCall outside the dispatcher, behavior stays\n // correct.\n\n // Tracks whether ensureAppOpen showed ConfirmOpenApp; if so the UI atom is\n // `openApp` and we owe a matching InteractionComplete.\n let openAppPromptShown = false;\n const onAppOpenPrompt = () => {\n openAppPromptShown = true;\n ctx.emit('ui-event', {\n type: EConnectorInteraction.ConfirmOpenApp,\n payload: { sessionId },\n });\n };\n\n // For bail-out paths that skip runOnce's finally (e.g. ensureAppOpen throws).\n const closeOpenAppUiIfShown = () => {\n if (openAppPromptShown) {\n ctx.emit('ui-event', {\n type: EConnectorInteraction.InteractionComplete,\n payload: { sessionId },\n });\n openAppPromptShown = false;\n }\n };\n\n // ① Pre-flight ensureAppOpen.\n try {\n await _ensureAppOpen(ctx, sessionId, appName, onAppOpenPrompt);\n } catch (err) {\n debugLog(\n '[LegacyChainCall] pre-flight ensureAppOpen failed:',\n appName,\n (err as Error)?.message\n );\n closeOpenAppUiIfShown();\n throw ctx.wrapError(err, { defaultAppName: appName });\n }\n\n const runOnce = async (): Promise<T> => {\n let confirmEmitted = false;\n if (needsConfirmation) {\n ctx.emit('ui-event', {\n type: EConnectorInteraction.ConfirmOnDevice,\n payload: { sessionId },\n });\n confirmEmitted = true;\n }\n\n try {\n return await action(sessionId);\n } finally {\n // Symmetry: any prompt we showed (ConfirmOpenApp or ConfirmOnDevice)\n // is closed here, on both success and failure. If neither was shown,\n // we don't fire a stray Complete (the UI atom was already undefined).\n if (confirmEmitted || openAppPromptShown) {\n ctx.emit('ui-event', {\n type: EConnectorInteraction.InteractionComplete,\n payload: { sessionId },\n });\n openAppPromptShown = false;\n }\n }\n };\n\n try {\n return await runOnce();\n } catch (err) {\n if (!isLegacyWrongAppError(err, appName)) {\n debugLog('[LegacyChainCall] non-wrong-app failure:', appName, (err as Error)?.message);\n ctx.invalidateSession(sessionId);\n throw ctx.wrapError(err, { defaultAppName: appName });\n }\n\n // ② Wrong-app fallback: user may have switched app between ① and the\n // action, or some edge state slipped through. Re-ensure and retry once.\n debugLog('[LegacyChainCall] wrong-app detected, retrying:', appName);\n try {\n await _ensureAppOpen(ctx, sessionId, appName, onAppOpenPrompt);\n } catch (switchErr) {\n debugLog(\n '[LegacyChainCall] retry ensureAppOpen failed:',\n appName,\n (switchErr as Error)?.message\n );\n closeOpenAppUiIfShown();\n throw ctx.wrapError(switchErr, { defaultAppName: appName });\n }\n ctx.clearAllSigners();\n\n const result = await runOnce();\n debugLog('[LegacyChainCall] retry succeeded:', appName);\n return result;\n }\n}\n\nasync function _ensureAppOpen(\n ctx: ConnectorContext,\n sessionId: string,\n appName: string,\n onPrompt: () => void\n): Promise<void> {\n const dmk = await ctx.getOrCreateDmk();\n const appManager = new AppManager(dmk);\n await appManager.ensureAppOpen(sessionId, appName, onPrompt);\n}\n","import {\n CloseAppCommand,\n type DeviceManagementKit,\n GetAppAndVersionCommand,\n OpenAppCommand,\n isSuccessCommandResult,\n} from '@ledgerhq/device-management-kit';\nimport { HardwareErrorCode } from '@onekeyfe/hwk-adapter-core';\n\nimport { ERROR_TAG } from '../errors';\nimport { debugLog } from '../utils/debugLog';\n\n/**\n * Map of chain ticker symbols to the Ledger app name\n * that must be open to sign transactions for that chain.\n */\nexport const APP_NAME_MAP: Record<string, string> = {\n ETH: 'Ethereum',\n BTC: 'Bitcoin',\n SOL: 'Solana',\n TRX: 'Tron',\n XRP: 'XRP',\n ADA: 'Cardano',\n DOT: 'Polkadot',\n ATOM: 'Cosmos',\n};\n\n/** The name reported by the Ledger when it sits on the home screen. */\nconst DASHBOARD_APP_NAME = 'BOLOS';\n\ninterface AppManagerOptions {\n waitMs?: number;\n maxRetries?: number;\n}\n\n/**\n * Orchestrates opening / closing Ledger on-device apps so that the\n * correct signer application is running before any signing call.\n */\nexport class AppManager {\n private readonly _dmk: DeviceManagementKit;\n\n private readonly _waitMs: number;\n\n private readonly _maxRetries: number;\n\n constructor(dmk: DeviceManagementKit, options?: AppManagerOptions) {\n this._dmk = dmk;\n this._waitMs = options?.waitMs ?? 1000;\n this._maxRetries = options?.maxRetries ?? 10;\n }\n\n /**\n * Return the Ledger app name for a given chain ticker,\n * or undefined if the chain is not supported.\n */\n static getAppName(chain: string): string | undefined {\n return APP_NAME_MAP[chain];\n }\n\n /**\n * Ensure the target app is open on the device identified by `sessionId`.\n *\n * Flow:\n * 1. Check the currently running app.\n * 2. If it is already the target, return immediately.\n * 3. If a different app is running (not dashboard), close it first.\n * 4. Open the target app.\n * 5. Poll until the device confirms the target app is running.\n */\n /**\n * @param onConfirmOnDevice Called BEFORE OpenAppCommand is issued — the\n * device is about to display \"Open <app>\" on screen and wait for the\n * user's button press. UI consumers should show their \"open app\" prompt\n * in response. NOT called when the target app is already open (no user\n * interaction needed in that case).\n *\n * Important: OpenAppCommand is blocking. It does not resolve until the user\n * has physically confirmed on the device, so anything that runs AFTER\n * `await this._openApp(...)` lands AFTER the prompt is already gone.\n * Hence the callback must fire BEFORE that await.\n */\n async ensureAppOpen(\n sessionId: string,\n targetAppName: string,\n onConfirmOnDevice?: () => void\n ): Promise<void> {\n const currentApp = await this._getCurrentApp(sessionId);\n\n if (currentApp === targetAppName) {\n return;\n }\n\n // If we're not on the dashboard, close the current app first\n if (!this._isDashboard(currentApp)) {\n await this._closeCurrentApp(sessionId);\n // Wait for dashboard to become active\n await this._waitForApp(sessionId, DASHBOARD_APP_NAME);\n }\n\n // Notify UI BEFORE issuing the open-app APDU. OpenAppCommand blocks until\n // the user confirms on device, so by the time `_openApp` resolves the\n // prompt is already gone — the UI must be told ahead of the APDU.\n onConfirmOnDevice?.();\n\n // Open the target app — throws if not installed (0x6807).\n // Resolves only after the user has confirmed on the device screen.\n await this._openApp(sessionId, targetAppName);\n\n // Poll until the target app is confirmed open\n await this._waitForApp(sessionId, targetAppName);\n }\n\n // ---------------------------------------------------------------------------\n // Private helpers\n // ---------------------------------------------------------------------------\n\n private async _getCurrentApp(sessionId: string): Promise<string> {\n const result = await this._dmk.sendCommand({\n sessionId,\n command: new GetAppAndVersionCommand(),\n });\n if (isSuccessCommandResult(result)) {\n debugLog('[AppManager] currentApp:', result.data.name);\n return result.data.name;\n }\n // DMK returns errors as result.error rather than throwing — surface the\n // tag / errorCode / originalError so transport-level failures aren't\n // swallowed under a generic \"Failed to get current app\" string.\n const errResult = result as unknown as { error?: Record<string, unknown> };\n const dmkErr = errResult.error ?? {};\n const original = (dmkErr as { originalError?: unknown }).originalError;\n debugLog(\n '[AppManager] _getCurrentApp failed sessionId=',\n sessionId,\n 'tag=',\n (dmkErr as { _tag?: string })._tag,\n 'errorCode=',\n (dmkErr as { errorCode?: unknown }).errorCode,\n 'message=',\n (dmkErr as { message?: string }).message,\n 'originalErrorMessage=',\n (original as { message?: string })?.message ?? String(original ?? '')\n );\n throw Object.assign(\n new Error(\n (dmkErr as { message?: string }).message ?? 'Failed to get current app from device'\n ),\n {\n _tag: (dmkErr as { _tag?: string })._tag,\n errorCode: (dmkErr as { errorCode?: unknown }).errorCode,\n originalError: original,\n }\n );\n }\n\n private async _openApp(sessionId: string, appName: string): Promise<void> {\n const result = await this._dmk.sendCommand({\n sessionId,\n command: new OpenAppCommand({ appName }),\n });\n if (!isSuccessCommandResult(result)) {\n const { statusCode } = result as Record<string, unknown>;\n const hasStatusCode = statusCode != null && statusCode !== '';\n debugLog('[AppManager] openApp failed:', appName, 'statusCode:', statusCode);\n throw Object.assign(new Error(`Failed to open \"${appName}\"`), {\n _tag: ERROR_TAG.OpenAppCommand,\n code: hasStatusCode ? undefined : HardwareErrorCode.AppNotInstalled,\n errorCode: String(statusCode ?? ''),\n statusCode,\n appName,\n });\n }\n }\n\n private async _closeCurrentApp(sessionId: string): Promise<void> {\n debugLog('[AppManager] closeCurrentApp');\n await this._dmk.sendCommand({\n sessionId,\n command: new CloseAppCommand(),\n });\n }\n\n /**\n * Poll the device until the expected app is reported as running,\n * or throw after `_maxRetries` attempts.\n */\n private async _waitForApp(sessionId: string, expectedAppName: string): Promise<void> {\n let lastSeen = '';\n for (let i = 0; i < this._maxRetries; i++) {\n await this._wait();\n const current = await this._getCurrentApp(sessionId);\n lastSeen = current;\n if (current === expectedAppName) {\n return;\n }\n }\n debugLog(\n '[AppManager] waitForApp exhausted: expected=',\n expectedAppName,\n 'lastSeen=',\n lastSeen\n );\n throw new Error(\n `Ledger: failed to open \"${expectedAppName}\" after ${this._maxRetries} retries (last seen: ${lastSeen})`\n );\n }\n\n private _isDashboard(appName: string): boolean {\n return appName === DASHBOARD_APP_NAME;\n }\n\n private _wait(): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, this._waitMs));\n }\n}\n","import Transport from '@ledgerhq/hw-transport';\n\nimport type { DeviceManagementKit } from '@ledgerhq/device-management-kit';\n\n/**\n * Transport adapter that bridges Ledger's legacy hw-app-* SDKs to DMK's sendApdu.\n *\n * Legacy SDKs (hw-app-trx, hw-app-xrp, etc.) require a Transport instance.\n * This adapter wraps DMK's session-based sendApdu so legacy SDKs can run\n * over DMK's transport layer without a separate USB/HID connection.\n *\n * Usage:\n * const transport = new DmkTransport(dmk, sessionId);\n * const trx = new Trx(transport);\n * const address = await trx.getAddress(\"44'/195'/0'/0/0\");\n */\nexport class DmkTransport extends Transport {\n private _dmk: DeviceManagementKit;\n\n private _sessionId: string;\n\n constructor(dmk: DeviceManagementKit, sessionId: string) {\n super();\n this._dmk = dmk;\n this._sessionId = sessionId;\n }\n\n async exchange(apdu: Buffer): Promise<Buffer> {\n const response = await this._dmk.sendApdu({\n sessionId: this._sessionId,\n apdu: new Uint8Array(apdu),\n });\n\n // Legacy format: data + statusCode (2 bytes) concatenated\n const { data, statusCode } = response;\n const result = Buffer.alloc(data.length + 2);\n if (data.length > 0) {\n result.set(data, 0);\n }\n result.set(statusCode, data.length);\n return result;\n }\n\n async close(): Promise<void> {\n // DMK manages session lifecycle\n }\n}\n","/* eslint-disable max-classes-per-file -- both classes are duck-typed DMK DeviceAction implementations sharing the same internal types (OsVersionDeps / InternalApiLike / AnyState); splitting would push those types into a third file with no payoff. */\n/**\n * Duck-typed DMK DeviceAction implementations for the two flows DMK has no\n * typed wrapper for: fetching OS version and listing available apps in the\n * catalog. Both are routed through `executeDeviceAction` so the\n * `unlock-device` interaction surfaces through the same onInteraction\n * pipeline as every other call.\n */\nimport { DeviceActionStatus } from '@ledgerhq/device-management-kit';\nimport { Subject } from 'rxjs';\n\nimport type { GetOsVersionResponse } from '@ledgerhq/device-management-kit';\nimport type { Observable } from 'rxjs';\n\nexport interface DmkApplication {\n versionName: string;\n versionId: number;\n version: string;\n versionDisplayName: string | null;\n description: string | null;\n icon: string | null;\n bytes: number | null;\n currencyId: string | null;\n isDevTools: boolean;\n}\n\nexport type OsVersionDeps = {\n GetOsVersionCommand: new () => unknown;\n isSuccessCommandResult: (result: unknown) => result is { data: GetOsVersionResponse };\n};\n\ninterface InternalApiLike {\n sendCommand: (command: unknown) => Promise<unknown>;\n getManagerApiService: () => {\n getAppList: (deviceInfo: GetOsVersionResponse) => {\n run: () => Promise<{ isLeft: () => boolean; extract: () => unknown }>;\n };\n };\n}\n\ntype AnyState<T> =\n | { readonly status: DeviceActionStatus.NotStarted }\n | { readonly status: DeviceActionStatus.Pending; readonly intermediateValue: unknown }\n | { readonly status: DeviceActionStatus.Stopped }\n | { readonly status: DeviceActionStatus.Completed; readonly output: T }\n | { readonly status: DeviceActionStatus.Error; readonly error: unknown };\n\n// Wrapped as a DeviceAction (not raw sendCommand) so unlock-device interaction\n// flows through onInteraction like every other method.\nexport class GetOsVersionDeviceAction {\n readonly input = undefined;\n\n // eslint-disable-next-line no-useless-constructor, no-empty-function\n constructor(private readonly _deps: OsVersionDeps) {}\n\n _execute(internalApi: { sendCommand: (cmd: unknown) => Promise<unknown> }): {\n observable: Observable<AnyState<GetOsVersionResponse>>;\n cancel: () => void;\n } {\n const subject = new Subject<AnyState<GetOsVersionResponse>>();\n let cancelled = false;\n\n (async () => {\n try {\n subject.next({\n status: DeviceActionStatus.Pending,\n intermediateValue: { requiredUserInteraction: 'none' },\n });\n const result = await internalApi.sendCommand(new this._deps.GetOsVersionCommand());\n if (cancelled) return;\n if (!this._deps.isSuccessCommandResult(result)) {\n const errObj = (result as { error?: { message?: string } })?.error;\n throw new Error(errObj?.message ?? 'GetOsVersionCommand failed');\n }\n subject.next({ status: DeviceActionStatus.Completed, output: result.data });\n subject.complete();\n } catch (err) {\n if (cancelled) return;\n subject.next({ status: DeviceActionStatus.Error, error: err });\n subject.complete();\n }\n })();\n\n return {\n observable: subject.asObservable(),\n cancel: () => {\n cancelled = true;\n subject.next({ status: DeviceActionStatus.Stopped });\n subject.complete();\n },\n };\n }\n}\n\nexport class ListAvailableAppsDeviceAction {\n readonly input = undefined;\n\n private readonly _GetOsVersionCommand: new () => unknown;\n\n private readonly _isSuccessCommandResult: (\n result: unknown\n ) => result is { data: GetOsVersionResponse };\n\n constructor(deps: OsVersionDeps) {\n this._GetOsVersionCommand = deps.GetOsVersionCommand;\n this._isSuccessCommandResult = deps.isSuccessCommandResult;\n }\n\n _execute(internalApi: InternalApiLike): {\n observable: Observable<AnyState<DmkApplication[]>>;\n cancel: () => void;\n } {\n const subject = new Subject<AnyState<DmkApplication[]>>();\n let cancelled = false;\n\n (async () => {\n try {\n subject.next({\n status: DeviceActionStatus.Pending,\n intermediateValue: { requiredUserInteraction: 'none' },\n });\n\n const osVersionResult = await internalApi.sendCommand(new this._GetOsVersionCommand());\n if (cancelled) return;\n if (!this._isSuccessCommandResult(osVersionResult)) {\n const errObj = (osVersionResult as { error?: { message?: string } })?.error;\n throw new Error(errObj?.message ?? 'GetOsVersionCommand failed');\n }\n\n const managerApi = internalApi.getManagerApiService();\n const either = await managerApi.getAppList(osVersionResult.data).run();\n if (cancelled) return;\n if (either.isLeft()) {\n const httpErr = either.extract() as { message?: string };\n throw new Error(httpErr?.message ?? 'Manager API getAppList failed');\n }\n\n const apps = either.extract() as DmkApplication[];\n subject.next({ status: DeviceActionStatus.Completed, output: apps });\n subject.complete();\n } catch (err) {\n if (cancelled) return;\n subject.next({ status: DeviceActionStatus.Error, error: err });\n subject.complete();\n }\n })();\n\n return {\n observable: subject.asObservable(),\n cancel: () => {\n cancelled = true;\n subject.next({ status: DeviceActionStatus.Stopped });\n subject.complete();\n },\n };\n }\n}\n","/** Raised by DeviceApps.install when DMK reports the requested app is not in the catalog. */\nexport class AppNotFoundInCatalogError extends Error {\n readonly missingApplications: string[];\n\n constructor(missing: string[]) {\n super(`Ledger app not found in catalog: ${missing.join(', ')}`);\n this.name = 'AppNotFoundInCatalogError';\n this.missingApplications = missing;\n }\n}\n","import { deviceActionToPromise } from '../signer/deviceActionToPromise';\nimport { debugLog } from '../utils/debugLog';\nimport { GetOsVersionDeviceAction, ListAvailableAppsDeviceAction } from './customActions';\nimport { AppNotFoundInCatalogError } from './errors';\n\nimport type { DmkApplication } from './customActions';\nimport type { DeviceManagementKit, GetOsVersionResponse } from '@ledgerhq/device-management-kit';\nimport type { CancelReason } from '../signer/deviceActionToPromise';\n\nconst INSTALL_TIMEOUT_MS = 5 * 60_000;\n\nexport interface AppMetadata {\n versionName: string;\n versionId: number;\n version: string;\n versionDisplayName: string | null;\n description: string | null;\n icon: string | null;\n bytes: number | null;\n currencyId: string | null;\n isDevTools: boolean;\n}\n\n/**\n * Progress fraction reported by DMK's InstallOrUpdateAppsDeviceAction.\n * Note: DMK's raw `requiredUserInteraction` for install (e.g. allow-secure-connection,\n * allow-manager) is intentionally NOT exposed here — those signals are routed through\n * the public 'ui-event' channel (collapsed to EConnectorInteraction) and additionally\n * captured via debugLog in the connector for diagnosis.\n */\nexport interface InstallProgress {\n progress: number;\n}\n\nexport type InstallProgressCallback = (progress: InstallProgress) => void;\n\nexport interface InstallAppCallParams {\n appName: string;\n}\n\nexport interface ListInstalledAppsCallParams {\n unlockTimeout?: number;\n}\n\nexport interface FirmwareVersion {\n /** BOLOS version on the secure element — the user-facing firmware version. */\n seVersion: string;\n /** MCU SEPH (SE–MCU link protocol) version. */\n mcuSephVersion: string;\n /** MCU bootloader version. */\n mcuBootloaderVersion: string;\n /** Hardware revision (e.g. \"00\" / \"01\" on Nano X). */\n hwVersion: string;\n}\n\n/** Full GetOsVersionResponse projected to a plain serializable shape. */\nexport interface LedgerDeviceInfo extends FirmwareVersion {\n isBootloader: boolean;\n isOsu: boolean;\n targetId: number;\n seTargetId?: number;\n mcuTargetId?: number;\n /** Secure element flags as hex string (raw bytes turned readable). */\n seFlagsHex: string;\n}\n\n/**\n * OS-level device management (install, list apps). Mirrors SignerEth:\n * built fresh per call, consumer sets onInteraction / onRegisterCanceller.\n */\nexport class DeviceApps {\n onInteraction?: (interaction: string) => void;\n\n onRegisterCanceller?: (cancel: (reason?: CancelReason) => void) => void;\n\n /* eslint-disable no-useless-constructor, no-empty-function -- TS parameter properties pattern */\n constructor(\n private readonly _dmk: DeviceManagementKit,\n private readonly _sessionId: string,\n private readonly _ledgerKit: LedgerKitModule\n ) {}\n /* eslint-enable no-useless-constructor, no-empty-function */\n\n async listInstalled(options?: { unlockTimeout?: number }): Promise<AppMetadata[]> {\n const action = (this._dmk as unknown as DmkExecuteCapable).executeDeviceAction({\n sessionId: this._sessionId,\n deviceAction: new this._ledgerKit.ListAppsWithMetadataDeviceAction({\n input: { unlockTimeout: options?.unlockTimeout },\n }),\n });\n const result = await deviceActionToPromise<Array<DmkApplication | null>>(\n action,\n this.onInteraction,\n undefined,\n this.onRegisterCanceller\n );\n return result.filter((a): a is DmkApplication => a !== null).map(applicationToMetadata);\n }\n\n // Catalog lookup via custom device action — DMK has no typed wrapper for this.\n async listAvailable(): Promise<AppMetadata[]> {\n const customAction = new ListAvailableAppsDeviceAction({\n GetOsVersionCommand: this._ledgerKit.GetOsVersionCommand,\n isSuccessCommandResult: this._ledgerKit.isSuccessCommandResult,\n });\n const action = (this._dmk as unknown as DmkExecuteCapable).executeDeviceAction({\n sessionId: this._sessionId,\n deviceAction: customAction,\n });\n const result = await deviceActionToPromise<DmkApplication[]>(\n action,\n this.onInteraction,\n undefined,\n this.onRegisterCanceller\n );\n return result.map(applicationToMetadata);\n }\n\n async getFirmwareVersion(): Promise<FirmwareVersion> {\n const v = await this._fetchOsVersion();\n return {\n seVersion: v.seVersion,\n mcuSephVersion: v.mcuSephVersion,\n mcuBootloaderVersion: v.mcuBootloaderVersion,\n hwVersion: v.hwVersion,\n };\n }\n\n async getDeviceInfo(): Promise<LedgerDeviceInfo> {\n const v = await this._fetchOsVersion();\n return {\n isBootloader: v.isBootloader,\n isOsu: v.isOsu,\n targetId: v.targetId,\n seTargetId: v.seTargetId,\n mcuTargetId: v.mcuTargetId,\n seVersion: v.seVersion,\n seFlagsHex: bytesToHex(v.seFlags),\n mcuSephVersion: v.mcuSephVersion,\n mcuBootloaderVersion: v.mcuBootloaderVersion,\n hwVersion: v.hwVersion,\n };\n }\n\n // Sole sendCommand path — routed via executeDeviceAction so unlock-device\n // interaction flows through onInteraction like the other methods.\n private async _fetchOsVersion(): Promise<GetOsVersionResponse> {\n const customAction = new GetOsVersionDeviceAction({\n GetOsVersionCommand: this._ledgerKit.GetOsVersionCommand,\n isSuccessCommandResult: this._ledgerKit.isSuccessCommandResult,\n });\n const action = (this._dmk as unknown as DmkExecuteCapable).executeDeviceAction({\n sessionId: this._sessionId,\n deviceAction: customAction,\n });\n return deviceActionToPromise<GetOsVersionResponse>(\n action,\n this.onInteraction,\n undefined,\n this.onRegisterCanceller\n );\n }\n\n async install(\n appName: string,\n onProgress?: InstallProgressCallback,\n options?: { unlockTimeout?: number }\n ): Promise<void> {\n if (!appName) throw new Error('DeviceApps.install: appName is required');\n debugLog('[DeviceApps] install:', appName);\n\n // Use InstallOrUpdateAppsDeviceAction (not InstallAppDeviceAction): it runs\n // UPDATE_DEVICE_METADATA → BUILD_INSTALL_PLAN → CHECK_IF_ENOUGH_MEMORY →\n // INSTALL_APPLICATION, so OOM fails fast (zero bytes written) and the refreshed\n // metadata feeds PredictOutOfMemoryTask accurate sizes — no client-side estimate.\n const action = (this._dmk as unknown as DmkExecuteCapable).executeDeviceAction({\n sessionId: this._sessionId,\n deviceAction: new this._ledgerKit.InstallOrUpdateAppsDeviceAction({\n input: {\n applications: [{ name: appName }],\n allowMissingApplication: false,\n unlockTimeout: options?.unlockTimeout,\n },\n }),\n });\n\n const result = await deviceActionToPromise<InstallOrUpdateAppsOutput>(\n action,\n this.onInteraction,\n INSTALL_TIMEOUT_MS,\n this.onRegisterCanceller,\n intermediateValue => {\n const iv = intermediateValue as\n | {\n requiredUserInteraction?: string;\n installPlan?: { currentProgress?: number } | null;\n }\n | undefined;\n // Surface DMK's install-specific interaction string (e.g. allow-secure-connection,\n // allow-manager, verify-app) into the debug log for post-hoc diagnosis. The\n // public 'ui-event' channel still emits the collapsed EConnectorInteraction so\n // existing UI consumers keep working.\n if (iv?.requiredUserInteraction && iv.requiredUserInteraction !== 'none') {\n debugLog('[DeviceApps] install interaction:', iv.requiredUserInteraction);\n }\n const progress = iv?.installPlan?.currentProgress;\n if (onProgress && typeof progress === 'number') {\n onProgress({ progress });\n }\n }\n );\n\n // DMK can resolve Completed with `missingApplications` populated when the\n // requested name is not in the catalog. allowMissingApplication=false should\n // make DMK reject, but we double-check on this side so the adapter never\n // returns success(undefined) for an install that didn't actually install.\n if (result?.missingApplications?.length > 0) {\n throw new AppNotFoundInCatalogError(result.missingApplications);\n }\n }\n}\n\nfunction bytesToHex(bytes: Uint8Array | undefined): string {\n if (!bytes) return '';\n return Array.from(bytes, b => b.toString(16).padStart(2, '0')).join('');\n}\n\nfunction applicationToMetadata(app: DmkApplication): AppMetadata {\n return {\n versionName: app.versionName,\n versionId: app.versionId,\n version: app.version,\n versionDisplayName: app.versionDisplayName,\n description: app.description,\n icon: app.icon,\n bytes: app.bytes,\n currencyId: app.currencyId,\n isDevTools: app.isDevTools,\n };\n}\n\n// Loosened DMK surface (we receive the module via dynamic importLedgerKit).\nexport interface LedgerKitModule {\n ListAppsWithMetadataDeviceAction: new (args: { input: unknown }) => unknown;\n InstallOrUpdateAppsDeviceAction: new (args: { input: unknown }) => unknown;\n GetOsVersionCommand: new () => unknown;\n isSuccessCommandResult: (result: unknown) => result is { data: GetOsVersionResponse };\n}\n\ninterface InstallOrUpdateAppsOutput {\n successfullyInstalled: unknown[];\n alreadyInstalled: string[];\n missingApplications: string[];\n}\n\ninterface DmkExecuteCapable {\n // Loose return: deviceActionToPromise narrows the observable shape per-call.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n executeDeviceAction(args: { sessionId: string; deviceAction: unknown }): any;\n}\n","import { DeviceApps } from './DeviceApps';\n\nimport type { LedgerKitModule } from './DeviceApps';\nimport type { DeviceManagementKit } from '@ledgerhq/device-management-kit';\n\n/** Per-call DeviceApps factory (mirrors SignerManager); DMK actions hold per-action state. */\nexport class DeviceAppsManager {\n private readonly _dmk: DeviceManagementKit;\n\n private readonly _importLedgerKit: (pkg: string) => Promise<unknown>;\n\n constructor(dmk: DeviceManagementKit, importLedgerKit: (pkg: string) => Promise<unknown>) {\n this._dmk = dmk;\n this._importLedgerKit = importLedgerKit;\n }\n\n async getOrCreate(sessionId: string): Promise<DeviceApps> {\n const ledgerKit = (await this._importLedgerKit(\n '@ledgerhq/device-management-kit'\n )) as LedgerKitModule;\n return new DeviceApps(this._dmk, sessionId, ledgerKit);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars, class-methods-use-this\n invalidate(_sessionId: string): void {}\n\n // eslint-disable-next-line class-methods-use-this\n clearAll(): void {}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAAAA,2BAcO;;;ACdP,8BAAsD;AAI/C,IAAM,4CACX;AAEK,SAAS,sCAA2E;AACzF,SAAO,OAAO,OAAO,IAAI,MAAM,yCAAyC,GAAG;AAAA,IACzE,MAAM,0CAAkB;AAAA,EAC1B,CAAC;AACH;AAYO,SAAS,cACd,MACA,OACA,SACA,KACA,QACe;AACf,QAAM,UAAoC,EAAE,OAAO,KAAK;AACxD,MAAI,YAAY,OAAW,SAAQ,UAAU;AAC7C,MAAI,QAAQ,OAAW,SAAQ,OAAO;AACtC,MAAI,WAAW,OAAW,SAAQ,SAAS;AAC3C,SAAO,EAAE,SAAS,OAAO,QAAQ;AACnC;AAQA,IAAM,qBAAqB,oBAAI,IAAI,CAAC,QAAQ,SAAS,QAAQ,SAAS,QAAQ,OAAO,CAAC;AAMtF,IAAM,sBAAsB,oBAAI,IAAI,CAAC,QAAQ,OAAO,CAAC;AAQrD,IAAM,kBAAkB,oBAAI,IAAI,CAAC,QAAQ,SAAS,QAAQ,SAAS,QAAQ,OAAO,CAAC;AAMnF,IAAM,0BAA0B,oBAAI,IAAI,CAAC,QAAQ,OAAO,CAAC;AAOzD,IAAM,uCAAuC;AAM7C,SAAS,mBAAmB,KAA6B;AACvD,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,QAAM,IAAI;AACV,MAAI,EAAE,SAAS,UAAU,iBAAiB,OAAO,EAAE,cAAc,UAAU;AACzE,WAAO,EAAE,UAAU,YAAY;AAAA,EACjC;AACA,QAAM,OAAO,EAAE;AACf,MAAI,MAAM,SAAS,UAAU,iBAAiB,OAAO,KAAK,cAAc,UAAU;AAChF,WAAO,KAAK,UAAU,YAAY;AAAA,EACpC;AACA,SAAO;AACT;AAOA,SAAS,eAAe,KAA6B;AACnD,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,QAAM,IAAI;AACV,MAAI,OAAO,EAAE,cAAc,YAAY,eAAe,KAAK,EAAE,SAAS,GAAG;AACvE,WAAO,EAAE,UAAU,YAAY;AAAA,EACjC;AACA,MAAI,OAAO,EAAE,eAAe,YAAY,OAAO,SAAS,EAAE,UAAU,GAAG;AACrE,WAAO,EAAE,WAAW,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG;AAAA,EAClD;AACA,MAAI,OAAO,EAAE,eAAe,YAAY,eAAe,KAAK,EAAE,UAAU,GAAG;AACzE,WAAO,EAAE,WAAW,YAAY;AAAA,EAClC;AACA,MAAI,EAAE,iBAAiB,MAAM;AAC3B,UAAM,SAAS,eAAe,EAAE,aAAa;AAC7C,QAAI,OAAQ,QAAO;AAAA,EACrB;AACA,MAAI,EAAE,SAAS,QAAQ,OAAO,EAAE,SAAS,UAAU;AACjD,UAAM,SAAS,eAAe,EAAE,KAAK;AACrC,QAAI,OAAQ,QAAO;AAAA,EACrB;AACA,SAAO;AACT;AAIA,SAAS,kBAAkB,KAAuC;AAChE,UAAQ,KAAK;AAAA,IACX,KAAK;AACH,aAAO,0CAAkB;AAAA,IAC3B;AACE,aAAO;AAAA,EACX;AACF;AAGA,SAAS,gBAAgB,KAAuC;AAC9D,UAAQ,KAAK;AAAA,IACX,KAAK;AACH,aAAO,0CAAkB;AAAA,IAC3B,KAAK;AACH,aAAO,0CAAkB;AAAA,IAC3B,KAAK;AACH,aAAO,0CAAkB;AAAA,IAC3B;AACE,aAAO;AAAA,EACX;AACF;AAGA,SAAS,eAAe,KAAuC;AAC7D,UAAQ,KAAK;AAAA,IACX,KAAK;AACH,aAAO,0CAAkB;AAAA,IAC3B,KAAK;AACH,aAAO,0CAAkB;AAAA,IAC3B;AACE,aAAO;AAAA,EACX;AACF;AAOA,SAAS,mBAAmB,SAA2C;AACrE,UAAQ,SAAS;AAAA,IACf,KAAK;AACH,aAAO,0CAAkB;AAAA,IAC3B,KAAK;AACH,aAAO,0CAAkB;AAAA,IAC3B,KAAK;AACH,aAAO,0CAAkB;AAAA,IAC3B,KAAK;AACH,aAAO,0CAAkB;AAAA,IAC3B;AACE,aAAO;AAAA,EACX;AACF;AAEA,SAAS,oBAAoB,KAAwC;AACnE,QAAM,UAAU,mBAAmB,GAAG;AACtC,MAAI,CAAC,QAAS,QAAO;AAIrB,MAAI,YAAY,QAAQ;AACtB,WAAO,yBAAyB,GAAG,IAAI,0CAAkB,0BAA0B;AAAA,EACrF;AAEA,SAAO,mBAAmB,OAAO;AACnC;AAIO,IAAM,YAAY;AAAA;AAAA,EAEvB,sBAAsB;AAAA;AAAA,EACtB,2BAA2B;AAAA;AAAA,EAC3B,mBAAmB;AAAA;AAAA,EACnB,sBAAsB;AAAA;AAAA,EACtB,aAAa;AAAA,EACb,gBAAgB;AAAA;AAAA,EAChB,sBAAsB;AAAA;AAAA;AAAA,EAGtB,cAAc;AAAA,EACd,qBAAqB;AAAA,EACrB,uBAAuB;AAAA,EACvB,gBAAgB;AAAA;AAAA,EAGhB,eAAe;AAAA,EACf,qBAAqB;AAAA,EACrB,gBAAgB;AAAA,EAChB,mBAAmB;AAAA,EACnB,oBAAoB;AAAA,EACpB,uBAAuB;AAAA,EACvB,oBAAoB;AAAA,EACpB,eAAe;AAAA,EACf,wBAAwB;AAAA,EACxB,sBAAsB;AAAA,EACtB,mBAAmB;AAAA,EACnB,qCAAqC;AAAA,EACrC,gCAAgC;AAAA,EAChC,YAAY;AAAA,EACZ,oBAAoB;AAAA,EACpB,kBAAkB;AAAA;AAAA;AAAA;AAAA,EAIlB,gBAAgB;AAClB;AAMO,SAAS,oBAAoB,KAAuB;AACzD,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,QAAM,IAAI;AACV,MAAI,EAAE,aAAa,QAAQ,mBAAmB,IAAI,OAAO,EAAE,SAAS,CAAC,EAAG,QAAO;AAC/E,MAAI,EAAE,cAAc,QAAQ,mBAAmB,IAAI,OAAO,EAAE,UAAU,CAAC,EAAG,QAAO;AACjF,MAAI,EAAE,SAAS,UAAU,aAAc,QAAO;AAC9C,MAAI,EAAE,iBAAiB,QAAQ,oBAAoB,EAAE,aAAa,EAAG,QAAO;AAC5E,MAAI,EAAE,SAAS,QAAQ,EAAE,QAAQ,oBAAoB,EAAE,KAAK,EAAG,QAAO;AACtE,SAAO;AACT;AAGO,SAAS,4BAA4B,KAAuB;AACjE,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,SAAQ,IAA0B,SAAS,UAAU;AACvD;AAYA,IAAM,uBAAuB,oBAAI,IAAY;AAAA,EAC3C,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AACZ,CAAC;AACM,SAAS,yBAAyB,KAAuB;AAC9D,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,QAAM,MAAO,IAA0B;AACvC,MAAI,OAAO,qBAAqB,IAAI,GAAG,EAAG,QAAO;AACjD,QAAM,OAAQ,IAAoC;AAClD,MAAI,QAAQ,QAAQ,yBAAyB,IAAI,EAAG,QAAO;AAC3D,SAAO;AACT;AAIA,IAAM,wBAAqC,oBAAI,IAAI;AAAA,EACjD,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AACZ,CAAC;AAED,IAAM,wBAAqC,oBAAI,IAAI;AAAA,EACjD,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA;AAAA;AAAA,EAGV,UAAU;AACZ,CAAC;AAED,IAAM,mBAAgC,oBAAI,IAAI,CAAC,UAAU,iBAAiB,CAAC;AAE3E,IAAM,2BAAwC,oBAAI,IAAI;AAAA,EACpD,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AACZ,CAAC;AAEM,SAAS,uBAAuB,KAAuB;AAC5D,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,QAAM,MAAO,IAA0B;AACvC,MAAI,OAAO,sBAAsB,IAAI,GAAG,EAAG,QAAO;AAElD,QAAM,IAAI;AACV,MAAI,EAAE,iBAAiB,QAAQ,uBAAuB,EAAE,aAAa,EAAG,QAAO;AAC/E,MAAI,EAAE,SAAS,QAAQ,EAAE,QAAQ,uBAAuB,EAAE,KAAK,EAAG,QAAO;AACzE,SAAO;AACT;AAIO,SAAS,qBAAqB,KAAuB;AAC1D,SAAO,OAAO,QAAQ,YAAY,sBAAsB,IAAI,GAAG;AACjE;AAGA,SAAS,cAAc,KAAc,SAA+B;AAClE,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,QAAM,IAAI;AACV,MAAI,EAAE,aAAa,QAAQ,QAAQ,IAAI,OAAO,EAAE,SAAS,CAAC,EAAG,QAAO;AACpE,MAAI,EAAE,cAAc,QAAQ,QAAQ,IAAI,OAAO,EAAE,UAAU,CAAC,EAAG,QAAO;AACtE,MAAI,EAAE,iBAAiB,QAAQ,cAAc,EAAE,eAAe,OAAO,EAAG,QAAO;AAC/E,MAAI,EAAE,SAAS,QAAQ,EAAE,QAAQ,cAAc,EAAE,OAAO,OAAO,EAAG,QAAO;AACzE,SAAO;AACT;AAEA,SAAS,yBAAyB,KAAuB;AACvD,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,QAAM,IAAI;AAEV,MAAI,EAAE,cAAc,qCAAsC,QAAO;AAEjE,MACE,MAAM,QAAQ,EAAE,kBAAkB,KAClC,EAAE,mBAAmB,SAAS,oCAAoC,GAClE;AACA,WAAO;AAAA,EACT;AAEA,MAAI,EAAE,iBAAiB,QAAQ,yBAAyB,EAAE,aAAa,EAAG,QAAO;AACjF,MAAI,EAAE,SAAS,QAAQ,EAAE,QAAQ,yBAAyB,EAAE,KAAK,EAAG,QAAO;AAC3E,SAAO;AACT;AAEA,SAAS,sBAAsB,KAAuB;AACpD,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,QAAM,MAAO,IAA0B;AACvC,MAAI,OAAO,sBAAsB,IAAI,GAAG,EAAG,QAAO;AAClD,QAAM,IAAI;AACV,MAAI,EAAE,iBAAiB,QAAQ,sBAAsB,EAAE,aAAa,EAAG,QAAO;AAC9E,MAAI,EAAE,SAAS,QAAQ,EAAE,QAAQ,sBAAsB,EAAE,KAAK,EAAG,QAAO;AACxE,SAAO;AACT;AAEA,SAAS,kBAAkB,KAAuB;AAChD,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,QAAM,MAAO,IAA0B;AACvC,MAAI,OAAO,iBAAiB,IAAI,GAAG,EAAG,QAAO;AAC7C,QAAM,IAAI;AACV,MAAI,EAAE,iBAAiB,QAAQ,kBAAkB,EAAE,aAAa,EAAG,QAAO;AAC1E,MAAI,EAAE,SAAS,QAAQ,EAAE,QAAQ,kBAAkB,EAAE,KAAK,EAAG,QAAO;AACpE,SAAO;AACT;AAGO,SAAS,oBAAoB,KAAuB;AACzD,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,QAAM,IAAI;AACV,MAAI,EAAE,SAAS,UAAU,oBAAqB,QAAO;AACrD,MAAI,OAAO,EAAE,YAAY,YAAY,2BAA2B,KAAK,EAAE,OAAO,EAAG,QAAO;AACxF,MAAI,cAAc,KAAK,mBAAmB,EAAG,QAAO;AACpD,SAAO;AACT;AAGO,SAAS,gBAAgB,KAAuB;AACrD,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,QAAM,IAAI;AACV,MAAI,EAAE,SAAS,UAAU,kBAAkB,EAAE,SAAS,UAAU,mBAAmB;AACjF,QAAI,cAAc,KAAK,eAAe,EAAG,QAAO;AAAA,EAClD;AACA,MAAI,OAAO,EAAE,YAAY,UAAU;AACjC,UAAM,MAAM,EAAE,QAAQ,YAAY;AAClC,QAAI,IAAI,SAAS,WAAW,KAAK,IAAI,SAAS,UAAU,KAAK,IAAI,SAAS,mBAAmB;AAC3F,aAAO;AAAA,EACX;AACA,MAAI,cAAc,KAAK,eAAe,EAAG,QAAO;AAChD,SAAO;AACT;AAGO,SAAS,uBAAuB,KAAuB;AAC5D,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,QAAM,IAAI;AACV,MAAI,OAAO,EAAE,YAAY,YAAY,uBAAuB,KAAK,EAAE,OAAO,EAAG,QAAO;AACpF,MAAI,cAAc,KAAK,uBAAuB,EAAG,QAAO;AACxD,SAAO;AACT;AAGO,SAAS,mBAAmB,KAAuB;AACxD,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,QAAM,IAAI;AACV,SAAO,EAAE,SAAS;AACpB;AAGO,SAAS,0BAA0B,KAAuB;AAC/D,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,QAAM,IAAI;AACV,QAAM,MAAM,EAAE;AACd,MAAI,OAAO,QAAQ,YAAY,yBAAyB,IAAI,GAAG,EAAG,QAAO;AACzE,MAAI,OAAO,EAAE,YAAY,UAAU;AACjC,UAAM,MAAM,EAAE,QAAQ,YAAY;AAClC,QACE,IAAI,SAAS,cAAc,KAC3B,IAAI,SAAS,WAAW,KACxB,IAAI,SAAS,WAAW,KACxB,IAAI,SAAS,WAAW;AAExB,aAAO;AAAA,EACX;AACA,SAAO;AACT;AAMA,IAAM,eAAe,oBAAI,IAAI;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAGM,SAAS,eAAe,KAAuB;AACpD,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,QAAM,IAAI;AACV,MAAI,OAAO,EAAE,SAAS,YAAY,aAAa,IAAI,EAAE,IAAI,EAAG,QAAO;AACnE,MAAI,EAAE,SAAS,0CAAkB,iBAAkB,QAAO;AAC1D,SAAO;AACT;AAGO,SAAS,iBAAiB,KAAuB;AACtD,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,QAAM,MAAO,IAAgC;AAC7C,MAAI,QAAQ,UAAU,eAAgB,QAAO;AAC7C,SAAO,eAAe,GAAG,MAAM;AACjC;AAGO,SAAS,iBAAiB,KAAuB;AACtD,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,QAAM,MAAO,IAAgC;AAC7C,SACE,QAAQ,UAAU;AAAA,EAClB,QAAQ,UAAU,yBAClB,QAAQ,UAAU;AAEtB;AAGO,SAAS,qBAAqB,KAAuB;AAC1D,SAAO,iBAAiB,GAAG,KAAK,iBAAiB,GAAG;AACtD;AAOO,SAAS,eACd,KACA,MAKA;AAIA,MAAI,kBAAkB;AACtB,MAAI,eAAe,OAAO;AACxB,sBAAkB,IAAI;AAAA,EACxB,WAAW,OAAO,OAAO,QAAQ,UAAU;AACzC,UAAM,IAAI;AACV,sBAAkB,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,KAAK,UAAU,GAAG,CAAC;AAAA,EAC/E;AAEA,MAAI;AAGJ,MAAI,oBAAoB,GAAG,GAAG;AAC5B,WAAO,0CAAkB;AAAA,EAC3B,WAAW,4BAA4B,GAAG,KAAK,sBAAsB,GAAG,GAAG;AACzE,WAAO,0CAAkB;AAAA,EAC3B,WAAW,kBAAkB,GAAG,GAAG;AACjC,WAAO,0CAAkB;AAAA,EAC3B,WAAW,yBAAyB,GAAG,GAAG;AACxC,WAAO,0CAAkB;AAAA,EAC3B,WAAW,oBAAoB,GAAG,GAAG;AAGnC,WAAO,0CAAkB;AAAA,EAC3B,WAAW,gBAAgB,GAAG,GAAG;AAC/B,WAAO,0CAAkB;AAAA,EAC3B,WAAW,uBAAuB,GAAG,GAAG;AACtC,WAAO,0CAAkB;AAAA,EAC3B,WAAW,mBAAmB,GAAG,GAAG;AAClC,WAAO,0CAAkB;AAAA,EAC3B,WAAW,0BAA0B,GAAG,GAAG;AACzC,WAAO,0CAAkB;AAAA,EAC3B,WAAW,eAAe,GAAG,GAAG;AAC9B,WAAO,0CAAkB;AAAA,EAC3B,OAAO;AACL,UAAM,YAAY,oBAAoB,GAAG;AAGzC,UAAM,UAAU,YAAY,OAAO,eAAe,GAAG;AACrD,UAAM,cAAc,UAChB,kBAAkB,OAAO,KAAK,gBAAgB,OAAO,KAAK,eAAe,OAAO,IAChF;AAEJ,WAAO,aAAa,eAAe,0CAAkB;AAAA,EACvD;AAEA,QAAM,aACJ,OAAO,OAAO,QAAQ,WAChB,IAAgC,UAClC;AACN,QAAM,UAAU,cAAc,MAAM;AAEpC,SAAO,EAAE,MAAM,aAAS,4CAAmB,MAAM,eAAe,GAAG,QAAQ;AAC7E;;;AC/hBO,SAAS,wBAAwB,WAA6B;AACnE,QAAM,aAAa,WAAW,YAAY;AAC1C,SAAO,eAAe,SAAS,YAAY,SAAS,MAAM,MAAM;AAClE;AAEO,SAAS,0BAA0B,gBAA0C;AAClF,SAAO,mBAAmB;AAC5B;AAEO,SAAS,sBACd,gBACA,YACS;AACT,SAAO,0BAA0B,cAAc,KAAK,wBAAwB,WAAW,SAAS;AAClG;;;ACTA,IAAM,YAAY,oBAAI,IAAsB;AAErC,SAAS,WAAW,UAAwC;AACjE,YAAU,IAAI,QAAQ;AACtB,SAAO,MAAM;AACX,cAAU,OAAO,QAAQ;AAAA,EAC3B;AACF;AAEO,SAAS,YAAY,UAAkC;AAC5D,YAAU,OAAO,QAAQ;AAC3B;AAEO,SAAS,aAAa,OAAuB;AAClD,MAAI,UAAU,SAAS,EAAG;AAC1B,aAAW,YAAY,WAAW;AAChC,QAAI;AACF,eAAS,KAAK;AAAA,IAChB,QAAQ;AAAA,IAER;AAAA,EACF;AACF;AAGO,SAAS,QAAQ,UAA6B,MAAuB;AAC1E,MAAI,UAAU,SAAS,EAAG;AAC1B,QAAM,UAAU,KAAK,IAAI,OAAM,OAAO,MAAM,WAAW,IAAI,cAAc,CAAC,CAAE,EAAE,KAAK,GAAG;AACtF,eAAa,EAAE,MAAM,OAAO,OAAO,QAAQ,CAAC;AAC9C;AAEA,SAAS,cAAc,OAAwB;AAC7C,MAAI,iBAAiB,OAAO;AAC1B,WAAO,MAAM,QAAQ,GAAG,MAAM,OAAO;AAAA,EAAK,MAAM,KAAK,KAAK,MAAM;AAAA,EAClE;AACA,MAAI;AACF,WAAO,KAAK,UAAU,KAAK;AAAA,EAC7B,QAAQ;AACN,WAAO,OAAO,KAAK;AAAA,EACrB;AACF;;;ACtDO,SAAS,YAAY,MAAuB;AACjD,UAAQ,SAAS,GAAG,IAAI;AAC1B;AAEO,SAAS,cAAc,MAAuB;AACnD,UAAQ,SAAS,GAAG,IAAI;AAC1B;;;AJ4FA,SAAS,0BAA0B,UAAkB,QAAwB;AAC3E,SAAO,0BAA0B,QAAQ,SAAS,MAAM;AAC1D;AAOA,IAAM,2BAA2B;AAEjC,SAAS,wBAAwB,MAA6B;AAC5D,QAAM,WAAW,KAAK,QAAQ,QAAQ,EAAE,EAAE,MAAM,GAAG;AACnD,MAAI,SAAS,SAAS,EAAG,QAAO;AAChC,QAAM,aAAa,SAAS,CAAC,EAAE,QAAQ,UAAU,EAAE;AACnD,QAAM,eAAe,SAAS,YAAY,EAAE;AAC5C,SAAO,OAAO,SAAS,YAAY,IAAI,eAAe;AACxD;AAEO,IAAM,iBAAN,MAAM,eAAyC;AAAA,EAmCpD,YAAY,WAAuB,SAAwC;AAlC3E,SAAS,SAAS;AAIlB,SAAiB,UAAU,IAAI,2CAAoC;AAEnE,SAAQ,qBAAqB,oBAAI,IAAwB;AAEzD,SAAQ,YAAY,oBAAI,IAAoB;AAE5C,SAAiB,cAAc,IAAI,2CAAkB;AAOrD;AAAA;AAAA;AAAA;AAAA;AAAA,SAAQ,oCAAoC;AAW5C;AAAA,SAAQ,4BAAoD;AAguB5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAQ,qBAA6C;AA0iCrD;AAAA;AAAA;AAAA,SAAQ,uBAAuB,CAAC,SAA4C;AAC1E,YAAM,aAAa,KAAK,4BAA4B,KAAK,MAAM;AAC/D,WAAK,mBAAmB,IAAI,WAAW,WAAW,UAAU;AAG5D,WAAK,UAAU,OAAO,WAAW,SAAS;AAC1C,WAAK,QAAQ,KAAK,gCAAO,SAAS;AAAA,QAChC,MAAM,gCAAO;AAAA,QACb,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAEA,SAAQ,0BAA0B,CAAC,SAAsC;AACvE,WAAK,mBAAmB,OAAO,KAAK,SAAS;AAC7C,WAAK,UAAU,OAAO,KAAK,SAAS;AACpC,WAAK,QAAQ,KAAK,gCAAO,YAAY;AAAA,QACnC,MAAM,gCAAO;AAAA,QACb,SAAS,EAAE,WAAW,KAAK,UAAU;AAAA,MACvC,CAAC;AAAA,IACH;AAOA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAQ,mBAAmB,CAAC,UAAkC;AAC5D,UAAI,MAAM,SAAS,+CAAsB,oBAAoB;AAC3D,YAAI;AACJ,mBAAW,CAAC,KAAK,GAAG,KAAK,KAAK,WAAW;AACvC,cAAI,QAAQ,MAAM,QAAQ,WAAW;AACnC,wBAAY;AACZ;AAAA,UACF;AAAA,QACF;AACA,YAAI,CAAC,WAAW;AACd;AAAA,YACE;AAAA,YACA,MAAM,QAAQ;AAAA,UAChB;AACA;AAAA,QACF;AACA,aAAK,QAAQ,KAAK,YAAY;AAAA,UAC5B,MAAM,+CAAsB;AAAA,UAC5B,SAAS;AAAA,YACP;AAAA,YACA,SAAS,MAAM,QAAQ;AAAA,YACvB,UAAU,MAAM,QAAQ;AAAA,UAC1B;AAAA,QACF,CAAC;AACD;AAAA,MACF;AACA,WAAK,QAAQ,KAAK,YAAY,KAAK;AAAA,IACrC;AAxzDE,SAAK,YAAY;AACjB,SAAK,yBAAyB,SAAS,kBAAkB;AACzD,SAAK,YAAY,IAAI,wCAAe;AACpC,SAAK,uBAAuB;AAAA,EAC9B;AAAA;AAAA,EAGA,IAAI,kBAAwC;AAC1C,WAAO,0BAA0B,KAAK,UAAU,cAAc,IAAI,QAAQ;AAAA,EAC5E;AAAA,EAEA,yBAA0C;AACxC,WAAO,KAAK,kBAAkB,CAAC,KAAK,eAAe,IAAI,CAAC;AAAA,EAC1D;AAAA;AAAA,EAGA,gBAAgB,OAAqC;AACnD,WAAO,QAAQ,QAAQ;AAAA,EACzB;AAAA;AAAA,EAGA,KAAK,SAAkC;AACrC,WAAO,QAAQ,QAAQ;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,aAAmB;AACjB,SAAK,mBAAmB,MAAM;AAC9B,SAAK,UAAU,MAAM;AACrB,SAAK,qBAAqB;AAC1B,SAAK,YAAY,MAAM;AACvB,SAAK,UAAU,MAAM;AACrB,SAAK,oCAAoC;AAAA,EAC3C;AAAA,EAEA,MAAM,UAAyB;AAC7B,SAAK,YAAY,MAAM;AACvB,SAAK,UAAU,MAAM;AACrB,SAAK,yBAAyB;AAC9B,SAAK,UAAU,MAAM;AACrB,SAAK,mBAAmB,MAAM;AAC9B,SAAK,UAAU,MAAM;AACrB,SAAK,oCAAoC;AACzC,SAAK,QAAQ,mBAAmB;AAAA,EAClC;AAAA,EAEA,WAAW,UAAiC;AAC1C,SAAK,YAAY,QAAQ,SAAS,MAAM,SAAS,OAAO;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,cAAc,SAAuD;AACzE,QAAI,SAAS,cAAc;AACzB,WAAK,2BAA2B,MAAM;AACtC,WAAK,UAAU,MAAM;AACrB,WAAK,qBAAqB;AAC1B,WAAK,4BAA4B;AACjC,WAAK,oCAAoC;AAAA,IAC3C;AAEA,UAAM,KAAK,wBAAwB;AAEnC,UAAM,UAAU,MAAM,KAAK,UAAU,cAAc;AAInD,SAAK,mBAAmB,MAAM;AAC9B,eAAW,KAAK,SAAS;AACvB,UAAI,EAAE,WAAW;AACf,aAAK,mBAAmB,IAAI,EAAE,WAAW,KAAK,4BAA4B,CAAC,CAAC;AAAA,MAC9E;AAAA,IACF;AAEA,QAAI,KAAK,mBAAmB,SAAS,GAAG;AACtC,YAAM,KAAK,wBAAwB;AAAA,IACrC;AAEA;AAAA,MACE,gDAAgD,KAAK,mBAAmB,IAAI,SAAS;AAAA,QACnF,GAAG,KAAK,mBAAmB,KAAK;AAAA,MAClC,EAAE,KAAK,GAAG,CAAC;AAAA,IACb;AACA,WAAO,MAAM,KAAK,KAAK,mBAAmB,OAAO,CAAC;AAAA,EACpD;AAAA;AAAA,EAGA,MAAc,oBAAmC;AAC/C,QAAI,KAAK,UAAU,SAAS,EAAG;AAC/B,UAAM,QAAQ,CAAC,GAAG,KAAK,UAAU,OAAO,CAAC;AACzC,SAAK,UAAU,MAAM;AACrB,eAAW,OAAO,OAAO;AACvB,UAAI;AACF,cAAM,KAAK,UAAU,WAAW,GAAG;AAAA,MACrC,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAAA,EAoBA,OAAe,uBAAuB,QAAuB;AAC3D,WAAO,OAAO,OAAO,IAAI,MAAM,uCAAuC,MAAM,EAAE,GAAG;AAAA,MAC/E,MAAM,2CAAkB;AAAA,IAC1B,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,cAAc,WAA8C;AAChE,QAAI;AACF,UAAI,0BAA0B,KAAK,UAAU,cAAc,KAAK,CAAC,WAAW;AAC1E,cAAM,OAAO,OAAO,IAAI,MAAM,mCAAmC,GAAG;AAAA,UAClE,MAAM,2CAAkB;AAAA,QAC1B,CAAC;AAAA,MACH;AAIA,UAAI,CAAC,0BAA0B,KAAK,UAAU,cAAc,GAAG;AAC7D,cAAM,KAAK,kBAAkB;AAAA,MAC/B;AAEA,YAAM,KAAK,wBAAwB,SAAS;AAE5C,YAAM,UAAU,MAAM,KAAK,UAAU,QAAQ,SAAS;AACtD,WAAK,UAAU,IAAI,WAAW,QAAQ,SAAS;AAE/C,UAAI,QAAQ,YAAY;AACtB,aAAK,mBAAmB,IAAI,WAAW,QAAQ,UAAU;AAAA,MAC3D;AAEA,iBAAO,kCAAQ,SAAS;AAAA,IAC1B,SAAS,KAAK;AACZ,aAAO,KAAK,eAAe,GAAG;AAAA,IAChC;AAAA,EACF;AAAA,EAEA,MAAM,iBAAiB,WAAkC;AACvD,UAAM,YAAY,KAAK,UAAU,IAAI,SAAS;AAC9C,QAAI,WAAW;AACb,YAAM,KAAK,UAAU,WAAW,SAAS;AACzC,WAAK,UAAU,OAAO,SAAS;AAAA,IACjC;AAAA,EACF;AAAA,EAEA,MAAM,cAAc,WAAmB,UAAiD;AACtF,UAAM,KAAK,wBAAwB,WAAW,QAAQ;AAItD,UAAM,SACJ,KAAK,mBAAmB,IAAI,SAAS,KACrC,MAAM,KAAK,KAAK,mBAAmB,OAAO,CAAC,EAAE,KAAK,OAAK,EAAE,aAAa,QAAQ;AAEhF,QAAI,QAAQ;AACV,iBAAO,kCAAQ,MAAM;AAAA,IACvB;AAEA,eAAO;AAAA,MACL,2CAAkB;AAAA,MAClB;AAAA,IACF;AAAA,EACF;AAAA,EAEA,qBAAwC;AACtC,WAAO,CAAC,OAAO,OAAO,OAAO,MAAM;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,UACZ,WACA,UACA,OACA,QACA,QACA,cACA,kBAAkB,OACI;AACtB,QAAI;AACF,YAAM,SAAS,MAAM,KAAK;AAAA,QACxB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,UACE;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,iBAAO,kCAAQ,MAAW;AAAA,IAC5B,SAAS,KAAK;AACZ,aAAO,KAAK,eAAe,GAAG;AAAA,IAChC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMA,cACE,WACA,UACA,QACA,cACA;AACA,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,mBACE,WACA,UACA,QACA,cACA;AACA,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,eACE,WACA,UACA,QACA,cACA;AACA,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,iBACE,WACA,UACA,QACA,cACA;AACA,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMA,cACE,WACA,UACA,QACA,cACA;AACA,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,gBACE,WACA,UACA,QACA,cACA;AACA,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,mBACE,WACA,UACA,QACA,cACA;AACA,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,YACE,WACA,UACA,QACA,cACA;AACA,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,eACE,WACA,UACA,QACA,cACA;AACA,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,wBAAwB,WAAmB,UAAkB,cAAkC;AAC7F,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,CAAC;AAAA,MACD;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMA,cACE,WACA,UACA,QACA,cACA;AACA,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,mBACE,WACA,UACA,QACA,cACA;AACA,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,eACE,WACA,UACA,QACA,cACA;AACA,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMA,eACE,WACA,UACA,QACA,cACA;AACA,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,oBACE,WACA,UACA,QACA,cACA;AACA,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,gBACE,WACA,UACA,QACA,cACA;AACA,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;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","names":["import_hwk_adapter_core","import_hwk_adapter_core","import_hwk_adapter_core","import_hwk_adapter_core","import_hwk_adapter_core","import_hwk_adapter_core","import_hwk_adapter_core","INTERACTIVE_TIMEOUT_MS","import_hwk_adapter_core","ContextModuleBuilder","import_hwk_adapter_core","import_hwk_adapter_core","import_device_management_kit","import_hwk_adapter_core","hasStatusCode","Transport","Trx","import_device_management_kit","bytesToHex"]}
|