@onekeyfe/hwk-adapter-core 1.2.0-alpha.1 → 1.2.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -61,6 +61,8 @@ declare enum HardwareErrorCode {
61
61
  * (generic) and from DeviceLocked (Secure Element actually locked).
62
62
  */
63
63
  BlePairingTimeout = 10304,
64
+ /** Remote network failure reaching a vendor's servers (HTTP/WS). Distinct from TransportError (local USB/BLE link). */
65
+ NetworkError = 10305,
64
66
  PinInvalid = 10400,
65
67
  PinCancelled = 10401,
66
68
  PassphraseRejected = 10402,
@@ -105,6 +107,27 @@ declare enum HardwareErrorCode {
105
107
  * next chain is harassment, not helpful.
106
108
  */
107
109
  declare const ORPHAN_ELIGIBLE_ERROR_CODES: number[];
110
+ interface IHwkErrorPayload {
111
+ code: HardwareErrorCode;
112
+ message: string;
113
+ appName?: string;
114
+ _tag?: string;
115
+ params?: Record<string, unknown>;
116
+ }
117
+ type HwkError = Error & {
118
+ code: HardwareErrorCode;
119
+ appName?: string;
120
+ _tag?: string;
121
+ params?: Record<string, unknown>;
122
+ };
123
+ /**
124
+ * Canonical throwable for HWK adapters. Plain Error + canonical extra fields,
125
+ * shape-compatible with `rehydrateConnectorError` so locally-thrown and
126
+ * cross-boundary errors are indistinguishable to downstream classifiers
127
+ * (`err.code` / `err._tag` / `err.appName`). Do NOT mutate caught errors
128
+ * with `Object.assign` — construct a fresh one via this factory.
129
+ */
130
+ declare function createHwkError(payload: IHwkErrorPayload): HwkError;
108
131
 
109
132
  interface Success<T> {
110
133
  success: true;
@@ -717,6 +740,30 @@ interface ICommonCallParams {
717
740
  */
718
741
  autoInstallApp?: boolean;
719
742
  }
743
+ interface AllNetworkAddressParams {
744
+ network: string;
745
+ path: string;
746
+ showOnDevice?: boolean;
747
+ methodName: 'evmGetAddress' | 'btcGetAddress' | 'btcGetPublicKey' | 'solGetAddress' | 'tronGetAddress';
748
+ [key: string]: unknown;
749
+ }
750
+ interface AllNetworkGetAddressParams extends ICommonCallParams {
751
+ bundle: AllNetworkAddressParams[];
752
+ }
753
+ type AllNetworkAddressResponsePayload = Record<string, unknown> & {
754
+ error?: string;
755
+ code?: HardwareErrorCode | number;
756
+ errorCode?: string | number;
757
+ connectId?: string;
758
+ deviceId?: string;
759
+ chainFingerprint?: string;
760
+ chainFingerprintChain?: ChainForFingerprint;
761
+ params?: Record<string, unknown>;
762
+ };
763
+ type AllNetworkAddressResponse = AllNetworkAddressParams & {
764
+ success: boolean;
765
+ payload?: AllNetworkAddressResponsePayload;
766
+ };
720
767
  interface PassphraseResponse {
721
768
  passphrase: string;
722
769
  /** If true, passphrase will be entered on the device. `passphrase` field is ignored. */
@@ -973,6 +1020,7 @@ interface IHardwareWallet<TConfig = unknown> extends IEvmMethods, IBtcMethods, I
973
1020
  getSupportedChains(): ChainCapability[];
974
1021
  /** Abort the in-flight call. Omit connectId to cancel whatever is active. */
975
1022
  cancel(connectId?: string): void;
1023
+ allNetworkGetAddress(connectId: string, deviceId: string, params: AllNetworkGetAddressParams): Promise<Response<AllNetworkAddressResponse[]>>;
976
1024
  /** Respond to any pending `ui-request-*`. */
977
1025
  uiResponse(response: UiResponseEvent): void;
978
1026
  /**
@@ -1267,4 +1315,4 @@ declare function batchCall<TParam, TResult>(params: TParam[], callFn: (p: TParam
1267
1315
  total: number;
1268
1316
  }) => void): Promise<Response<TResult[]>>;
1269
1317
 
1270
- export { type ActiveJobInfo, type BtcAddress, type BtcGetAddressParams, type BtcGetPublicKeyParams, type BtcPublicKey, type BtcRefTransaction, type BtcSignMsgParams, type BtcSignPsbtParams, type BtcSignTxParams, type BtcSignature, type BtcSignedPsbt, type BtcSignedTx, type BtcTxInput, type BtcTxOutput, CHAIN_FINGERPRINT_PATHS, type ChainCapability, type ChainForFingerprint, type ConnectionType, type ConnectorCallResult, type ConnectorDevice, type ConnectorErrorParams, type ConnectorEventMap, type ConnectorEventType, type ConnectorSerializedError, type ConnectorSession, type ConnectorUiEvent, DEVICE, DEVICE_EVENT, type DeviceCapabilities, type DeviceChangeEvent, type DeviceConnectEvent, type DeviceDescriptor, type DeviceDisconnectEvent, type DeviceEvent, type DeviceEventListener, type DeviceInfo, DeviceJobQueue, type DevicePermissionDeniedReason, type DevicePermissionResponse, type DeviceTarget, EConnectorInteraction, type EIP712Domain, type EvmAddress, type EvmGetAddressParams, type EvmSignMsgParams, type EvmSignTxParams, type EvmSignTypedDataFull, type EvmSignTypedDataHash, type EvmSignTypedDataParams, type EvmSignature, type EvmSignedTx, type Failure, HardwareErrorCode, type HardwareEvent, type HardwareEventMap, type HardwareUiEvent, type IBtcMethods, type ICommonCallParams, type IConnector, type IEvmMethods, type IHardwareBridge, type IHardwareWallet, type ISolMethods, type ITronMethods, type JobOptions, ORPHAN_ELIGIBLE_ERROR_CODES, type PassphraseResponse, type QrDisplayData, type QrResponseData, type Response, SDK, type SdkEvent, type SearchDevicesOptions, type SolAddress, type SolGetAddressParams, type SolSignMsgParams, type SolSignTxParams, type SolSignature, type SolSignedTx, type Success, type TransportType, type TronAddress, type TronGetAddressParams, type TronSignMsgParams, type TronSignTxParams, type TronSignature, type TronSignedTx, TypedEventEmitter, UI_EVENT, UI_REQUEST, UI_REQUEST_CANCELLED_TAG, UI_REQUEST_DEFAULT_TIMEOUT_MS, UI_REQUEST_PREEMPTED_TAG, UI_REQUEST_TIMEOUT_TAG, UI_RESPONSE, type UiRequestEvent, UiRequestRegistry, type UiResponseEvent, type VendorType, batchCall, bytesToHex, compareSemver, createBridgedConnector, deriveDeviceFingerprint, enrichErrorMessage, ensure0x, failure, hexToBytes, padHex64, rehydrateConnectorError, serializeConnectorError, stripHex, success };
1318
+ export { type ActiveJobInfo, type AllNetworkAddressParams, type AllNetworkAddressResponse, type AllNetworkAddressResponsePayload, type AllNetworkGetAddressParams, type BtcAddress, type BtcGetAddressParams, type BtcGetPublicKeyParams, type BtcPublicKey, type BtcRefTransaction, type BtcSignMsgParams, type BtcSignPsbtParams, type BtcSignTxParams, type BtcSignature, type BtcSignedPsbt, type BtcSignedTx, type BtcTxInput, type BtcTxOutput, CHAIN_FINGERPRINT_PATHS, type ChainCapability, type ChainForFingerprint, type ConnectionType, type ConnectorCallResult, type ConnectorDevice, type ConnectorErrorParams, type ConnectorEventMap, type ConnectorEventType, type ConnectorSerializedError, type ConnectorSession, type ConnectorUiEvent, DEVICE, DEVICE_EVENT, type DeviceCapabilities, type DeviceChangeEvent, type DeviceConnectEvent, type DeviceDescriptor, type DeviceDisconnectEvent, type DeviceEvent, type DeviceEventListener, type DeviceInfo, DeviceJobQueue, type DevicePermissionDeniedReason, type DevicePermissionResponse, type DeviceTarget, EConnectorInteraction, type EIP712Domain, type EvmAddress, type EvmGetAddressParams, type EvmSignMsgParams, type EvmSignTxParams, type EvmSignTypedDataFull, type EvmSignTypedDataHash, type EvmSignTypedDataParams, type EvmSignature, type EvmSignedTx, type Failure, HardwareErrorCode, type HardwareEvent, type HardwareEventMap, type HardwareUiEvent, type HwkError, type IBtcMethods, type ICommonCallParams, type IConnector, type IEvmMethods, type IHardwareBridge, type IHardwareWallet, type IHwkErrorPayload, type ISolMethods, type ITronMethods, type JobOptions, ORPHAN_ELIGIBLE_ERROR_CODES, type PassphraseResponse, type QrDisplayData, type QrResponseData, type Response, SDK, type SdkEvent, type SearchDevicesOptions, type SolAddress, type SolGetAddressParams, type SolSignMsgParams, type SolSignTxParams, type SolSignature, type SolSignedTx, type Success, type TransportType, type TronAddress, type TronGetAddressParams, type TronSignMsgParams, type TronSignTxParams, type TronSignature, type TronSignedTx, TypedEventEmitter, UI_EVENT, UI_REQUEST, UI_REQUEST_CANCELLED_TAG, UI_REQUEST_DEFAULT_TIMEOUT_MS, UI_REQUEST_PREEMPTED_TAG, UI_REQUEST_TIMEOUT_TAG, UI_RESPONSE, type UiRequestEvent, UiRequestRegistry, type UiResponseEvent, type VendorType, batchCall, bytesToHex, compareSemver, createBridgedConnector, createHwkError, deriveDeviceFingerprint, enrichErrorMessage, ensure0x, failure, hexToBytes, padHex64, rehydrateConnectorError, serializeConnectorError, stripHex, success };
package/dist/index.d.ts CHANGED
@@ -61,6 +61,8 @@ declare enum HardwareErrorCode {
61
61
  * (generic) and from DeviceLocked (Secure Element actually locked).
62
62
  */
63
63
  BlePairingTimeout = 10304,
64
+ /** Remote network failure reaching a vendor's servers (HTTP/WS). Distinct from TransportError (local USB/BLE link). */
65
+ NetworkError = 10305,
64
66
  PinInvalid = 10400,
65
67
  PinCancelled = 10401,
66
68
  PassphraseRejected = 10402,
@@ -105,6 +107,27 @@ declare enum HardwareErrorCode {
105
107
  * next chain is harassment, not helpful.
106
108
  */
107
109
  declare const ORPHAN_ELIGIBLE_ERROR_CODES: number[];
110
+ interface IHwkErrorPayload {
111
+ code: HardwareErrorCode;
112
+ message: string;
113
+ appName?: string;
114
+ _tag?: string;
115
+ params?: Record<string, unknown>;
116
+ }
117
+ type HwkError = Error & {
118
+ code: HardwareErrorCode;
119
+ appName?: string;
120
+ _tag?: string;
121
+ params?: Record<string, unknown>;
122
+ };
123
+ /**
124
+ * Canonical throwable for HWK adapters. Plain Error + canonical extra fields,
125
+ * shape-compatible with `rehydrateConnectorError` so locally-thrown and
126
+ * cross-boundary errors are indistinguishable to downstream classifiers
127
+ * (`err.code` / `err._tag` / `err.appName`). Do NOT mutate caught errors
128
+ * with `Object.assign` — construct a fresh one via this factory.
129
+ */
130
+ declare function createHwkError(payload: IHwkErrorPayload): HwkError;
108
131
 
109
132
  interface Success<T> {
110
133
  success: true;
@@ -717,6 +740,30 @@ interface ICommonCallParams {
717
740
  */
718
741
  autoInstallApp?: boolean;
719
742
  }
743
+ interface AllNetworkAddressParams {
744
+ network: string;
745
+ path: string;
746
+ showOnDevice?: boolean;
747
+ methodName: 'evmGetAddress' | 'btcGetAddress' | 'btcGetPublicKey' | 'solGetAddress' | 'tronGetAddress';
748
+ [key: string]: unknown;
749
+ }
750
+ interface AllNetworkGetAddressParams extends ICommonCallParams {
751
+ bundle: AllNetworkAddressParams[];
752
+ }
753
+ type AllNetworkAddressResponsePayload = Record<string, unknown> & {
754
+ error?: string;
755
+ code?: HardwareErrorCode | number;
756
+ errorCode?: string | number;
757
+ connectId?: string;
758
+ deviceId?: string;
759
+ chainFingerprint?: string;
760
+ chainFingerprintChain?: ChainForFingerprint;
761
+ params?: Record<string, unknown>;
762
+ };
763
+ type AllNetworkAddressResponse = AllNetworkAddressParams & {
764
+ success: boolean;
765
+ payload?: AllNetworkAddressResponsePayload;
766
+ };
720
767
  interface PassphraseResponse {
721
768
  passphrase: string;
722
769
  /** If true, passphrase will be entered on the device. `passphrase` field is ignored. */
@@ -973,6 +1020,7 @@ interface IHardwareWallet<TConfig = unknown> extends IEvmMethods, IBtcMethods, I
973
1020
  getSupportedChains(): ChainCapability[];
974
1021
  /** Abort the in-flight call. Omit connectId to cancel whatever is active. */
975
1022
  cancel(connectId?: string): void;
1023
+ allNetworkGetAddress(connectId: string, deviceId: string, params: AllNetworkGetAddressParams): Promise<Response<AllNetworkAddressResponse[]>>;
976
1024
  /** Respond to any pending `ui-request-*`. */
977
1025
  uiResponse(response: UiResponseEvent): void;
978
1026
  /**
@@ -1267,4 +1315,4 @@ declare function batchCall<TParam, TResult>(params: TParam[], callFn: (p: TParam
1267
1315
  total: number;
1268
1316
  }) => void): Promise<Response<TResult[]>>;
1269
1317
 
1270
- export { type ActiveJobInfo, type BtcAddress, type BtcGetAddressParams, type BtcGetPublicKeyParams, type BtcPublicKey, type BtcRefTransaction, type BtcSignMsgParams, type BtcSignPsbtParams, type BtcSignTxParams, type BtcSignature, type BtcSignedPsbt, type BtcSignedTx, type BtcTxInput, type BtcTxOutput, CHAIN_FINGERPRINT_PATHS, type ChainCapability, type ChainForFingerprint, type ConnectionType, type ConnectorCallResult, type ConnectorDevice, type ConnectorErrorParams, type ConnectorEventMap, type ConnectorEventType, type ConnectorSerializedError, type ConnectorSession, type ConnectorUiEvent, DEVICE, DEVICE_EVENT, type DeviceCapabilities, type DeviceChangeEvent, type DeviceConnectEvent, type DeviceDescriptor, type DeviceDisconnectEvent, type DeviceEvent, type DeviceEventListener, type DeviceInfo, DeviceJobQueue, type DevicePermissionDeniedReason, type DevicePermissionResponse, type DeviceTarget, EConnectorInteraction, type EIP712Domain, type EvmAddress, type EvmGetAddressParams, type EvmSignMsgParams, type EvmSignTxParams, type EvmSignTypedDataFull, type EvmSignTypedDataHash, type EvmSignTypedDataParams, type EvmSignature, type EvmSignedTx, type Failure, HardwareErrorCode, type HardwareEvent, type HardwareEventMap, type HardwareUiEvent, type IBtcMethods, type ICommonCallParams, type IConnector, type IEvmMethods, type IHardwareBridge, type IHardwareWallet, type ISolMethods, type ITronMethods, type JobOptions, ORPHAN_ELIGIBLE_ERROR_CODES, type PassphraseResponse, type QrDisplayData, type QrResponseData, type Response, SDK, type SdkEvent, type SearchDevicesOptions, type SolAddress, type SolGetAddressParams, type SolSignMsgParams, type SolSignTxParams, type SolSignature, type SolSignedTx, type Success, type TransportType, type TronAddress, type TronGetAddressParams, type TronSignMsgParams, type TronSignTxParams, type TronSignature, type TronSignedTx, TypedEventEmitter, UI_EVENT, UI_REQUEST, UI_REQUEST_CANCELLED_TAG, UI_REQUEST_DEFAULT_TIMEOUT_MS, UI_REQUEST_PREEMPTED_TAG, UI_REQUEST_TIMEOUT_TAG, UI_RESPONSE, type UiRequestEvent, UiRequestRegistry, type UiResponseEvent, type VendorType, batchCall, bytesToHex, compareSemver, createBridgedConnector, deriveDeviceFingerprint, enrichErrorMessage, ensure0x, failure, hexToBytes, padHex64, rehydrateConnectorError, serializeConnectorError, stripHex, success };
1318
+ export { type ActiveJobInfo, type AllNetworkAddressParams, type AllNetworkAddressResponse, type AllNetworkAddressResponsePayload, type AllNetworkGetAddressParams, type BtcAddress, type BtcGetAddressParams, type BtcGetPublicKeyParams, type BtcPublicKey, type BtcRefTransaction, type BtcSignMsgParams, type BtcSignPsbtParams, type BtcSignTxParams, type BtcSignature, type BtcSignedPsbt, type BtcSignedTx, type BtcTxInput, type BtcTxOutput, CHAIN_FINGERPRINT_PATHS, type ChainCapability, type ChainForFingerprint, type ConnectionType, type ConnectorCallResult, type ConnectorDevice, type ConnectorErrorParams, type ConnectorEventMap, type ConnectorEventType, type ConnectorSerializedError, type ConnectorSession, type ConnectorUiEvent, DEVICE, DEVICE_EVENT, type DeviceCapabilities, type DeviceChangeEvent, type DeviceConnectEvent, type DeviceDescriptor, type DeviceDisconnectEvent, type DeviceEvent, type DeviceEventListener, type DeviceInfo, DeviceJobQueue, type DevicePermissionDeniedReason, type DevicePermissionResponse, type DeviceTarget, EConnectorInteraction, type EIP712Domain, type EvmAddress, type EvmGetAddressParams, type EvmSignMsgParams, type EvmSignTxParams, type EvmSignTypedDataFull, type EvmSignTypedDataHash, type EvmSignTypedDataParams, type EvmSignature, type EvmSignedTx, type Failure, HardwareErrorCode, type HardwareEvent, type HardwareEventMap, type HardwareUiEvent, type HwkError, type IBtcMethods, type ICommonCallParams, type IConnector, type IEvmMethods, type IHardwareBridge, type IHardwareWallet, type IHwkErrorPayload, type ISolMethods, type ITronMethods, type JobOptions, ORPHAN_ELIGIBLE_ERROR_CODES, type PassphraseResponse, type QrDisplayData, type QrResponseData, type Response, SDK, type SdkEvent, type SearchDevicesOptions, type SolAddress, type SolGetAddressParams, type SolSignMsgParams, type SolSignTxParams, type SolSignature, type SolSignedTx, type Success, type TransportType, type TronAddress, type TronGetAddressParams, type TronSignMsgParams, type TronSignTxParams, type TronSignature, type TronSignedTx, TypedEventEmitter, UI_EVENT, UI_REQUEST, UI_REQUEST_CANCELLED_TAG, UI_REQUEST_DEFAULT_TIMEOUT_MS, UI_REQUEST_PREEMPTED_TAG, UI_REQUEST_TIMEOUT_TAG, UI_RESPONSE, type UiRequestEvent, UiRequestRegistry, type UiResponseEvent, type VendorType, batchCall, bytesToHex, compareSemver, createBridgedConnector, createHwkError, deriveDeviceFingerprint, enrichErrorMessage, ensure0x, failure, hexToBytes, padHex64, rehydrateConnectorError, serializeConnectorError, stripHex, success };
package/dist/index.js CHANGED
@@ -41,6 +41,7 @@ __export(index_exports, {
41
41
  bytesToHex: () => bytesToHex2,
42
42
  compareSemver: () => compareSemver,
43
43
  createBridgedConnector: () => createBridgedConnector,
44
+ createHwkError: () => createHwkError,
44
45
  deriveDeviceFingerprint: () => deriveDeviceFingerprint,
45
46
  enrichErrorMessage: () => enrichErrorMessage,
46
47
  ensure0x: () => ensure0x,
@@ -79,6 +80,7 @@ var HardwareErrorCode = /* @__PURE__ */ ((HardwareErrorCode2) => {
79
80
  HardwareErrorCode2[HardwareErrorCode2["TransportNotAvailable"] = 10302] = "TransportNotAvailable";
80
81
  HardwareErrorCode2[HardwareErrorCode2["DevicePermissionDenied"] = 10303] = "DevicePermissionDenied";
81
82
  HardwareErrorCode2[HardwareErrorCode2["BlePairingTimeout"] = 10304] = "BlePairingTimeout";
83
+ HardwareErrorCode2[HardwareErrorCode2["NetworkError"] = 10305] = "NetworkError";
82
84
  HardwareErrorCode2[HardwareErrorCode2["PinInvalid"] = 10400] = "PinInvalid";
83
85
  HardwareErrorCode2[HardwareErrorCode2["PinCancelled"] = 10401] = "PinCancelled";
84
86
  HardwareErrorCode2[HardwareErrorCode2["PassphraseRejected"] = 10402] = "PassphraseRejected";
@@ -110,6 +112,14 @@ var ORPHAN_ELIGIBLE_ERROR_CODES = [
110
112
  10303 /* DevicePermissionDenied */,
111
113
  10304 /* BlePairingTimeout */
112
114
  ];
115
+ function createHwkError(payload) {
116
+ return Object.assign(new Error(payload.message), {
117
+ code: payload.code,
118
+ ...payload._tag !== void 0 && { _tag: payload._tag },
119
+ ...payload.appName !== void 0 && { appName: payload.appName },
120
+ ...payload.params !== void 0 && { params: payload.params }
121
+ });
122
+ }
113
123
 
114
124
  // src/types/response.ts
115
125
  function success(payload) {
@@ -584,6 +594,8 @@ function enrichErrorMessage(code, originalMessage) {
584
594
  return `${originalMessage}. Not enough free space on the device. Please uninstall some apps and try again.`;
585
595
  case 10302 /* TransportNotAvailable */:
586
596
  return `${originalMessage}. Ensure the device bridge/transport is available and running.`;
597
+ case 10305 /* NetworkError */:
598
+ return `${originalMessage}. Network error \u2014 check your internet connection and try again.`;
587
599
  case 10200 /* FirmwareTooOld */:
588
600
  return `${originalMessage}. Please update your device firmware.`;
589
601
  case 10104 /* DeviceNotInitialized */:
@@ -653,6 +665,7 @@ async function batchCall(params, callFn, onProgress) {
653
665
  bytesToHex,
654
666
  compareSemver,
655
667
  createBridgedConnector,
668
+ createHwkError,
656
669
  deriveDeviceFingerprint,
657
670
  enrichErrorMessage,
658
671
  ensure0x,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/types/errors.ts","../src/types/response.ts","../src/types/fingerprint.ts","../src/events/device.ts","../src/events/ui-request.ts","../src/events/sdk.ts","../src/utils/DeviceJobQueue.ts","../src/types/connector.ts","../src/utils/TypedEventEmitter.ts","../src/utils/UiRequestRegistry.ts","../src/utils/semver.ts","../src/utils/hex.ts","../src/utils/errorMessages.ts","../src/utils/batchCall.ts"],"sourcesContent":["export { HardwareErrorCode, ORPHAN_ELIGIBLE_ERROR_CODES } from './types/errors';\n\nexport type { Success, Failure, Response } from './types/response';\nexport { success, failure } from './types/response';\n\nexport type {\n VendorType,\n ConnectionType,\n TransportType,\n DeviceInfo,\n DeviceTarget,\n DeviceCapabilities,\n} from './types/device';\n\nexport type {\n EvmGetAddressParams,\n EvmAddress,\n EvmSignTxParams,\n EvmSignedTx,\n EvmSignMsgParams,\n EvmSignTypedDataParams,\n EvmSignTypedDataFull,\n EvmSignTypedDataHash,\n EIP712Domain,\n EvmSignature,\n IEvmMethods,\n} from './types/chain-evm';\n\nexport type {\n BtcGetAddressParams,\n BtcAddress,\n BtcGetPublicKeyParams,\n BtcPublicKey,\n BtcSignTxParams,\n BtcTxInput,\n BtcTxOutput,\n BtcRefTransaction,\n BtcSignedTx,\n BtcSignPsbtParams,\n BtcSignedPsbt,\n BtcSignMsgParams,\n BtcSignature,\n IBtcMethods,\n} from './types/chain-btc';\n\nexport type {\n SolGetAddressParams,\n SolAddress,\n SolSignTxParams,\n SolSignedTx,\n SolSignMsgParams,\n SolSignature,\n ISolMethods,\n} from './types/chain-sol';\n\nexport type {\n TronGetAddressParams,\n TronAddress,\n TronSignTxParams,\n TronSignedTx,\n TronSignMsgParams,\n TronSignature,\n ITronMethods,\n} from './types/chain-tron';\n\nexport type { QrDisplayData, QrResponseData } from './types/qr';\n\nexport type { ChainForFingerprint } from './types/fingerprint';\nexport { CHAIN_FINGERPRINT_PATHS, deriveDeviceFingerprint } from './types/fingerprint';\n\nexport type {\n IHardwareWallet,\n SearchDevicesOptions,\n PassphraseResponse,\n ChainCapability,\n ICommonCallParams,\n DeviceEvent,\n UiRequestEvent,\n SdkEvent,\n HardwareEvent,\n HardwareUiEvent,\n HardwareEventMap,\n DeviceEventListener,\n} from './types/wallet';\n\nexport { DEVICE_EVENT, DEVICE } from './events/device';\nexport { UI_EVENT, UI_REQUEST, UI_RESPONSE } from './events/ui-request';\nexport type {\n DevicePermissionDeniedReason,\n DevicePermissionResponse,\n UiResponseEvent,\n} from './events/ui-request';\nexport { SDK } from './events/sdk';\n\nexport type {\n DeviceDescriptor,\n DeviceConnectEvent,\n DeviceDisconnectEvent,\n DeviceChangeEvent,\n} from './types/transport';\n\nexport { DeviceJobQueue } from './utils/DeviceJobQueue';\nexport type { JobOptions, ActiveJobInfo } from './utils/DeviceJobQueue';\n\nexport type {\n ConnectorDevice,\n ConnectorSession,\n ConnectorEventType,\n ConnectorEventMap,\n ConnectorUiEvent,\n ConnectorCallResult,\n ConnectorSerializedError,\n ConnectorErrorParams,\n IConnector,\n IHardwareBridge,\n} from './types/connector';\nexport {\n createBridgedConnector,\n EConnectorInteraction,\n serializeConnectorError,\n rehydrateConnectorError,\n} from './types/connector';\n\nexport { TypedEventEmitter } from './utils/TypedEventEmitter';\nexport {\n UiRequestRegistry,\n UI_REQUEST_DEFAULT_TIMEOUT_MS,\n UI_REQUEST_PREEMPTED_TAG,\n UI_REQUEST_CANCELLED_TAG,\n UI_REQUEST_TIMEOUT_TAG,\n} from './utils/UiRequestRegistry';\nexport { compareSemver } from './utils/semver';\nexport { ensure0x, stripHex, padHex64, hexToBytes, bytesToHex } from './utils/hex';\nexport { enrichErrorMessage } from './utils/errorMessages';\nexport { batchCall } from './utils/batchCall';\n","/**\n * HWK HardwareErrorCode — independent namespace from the legacy\n * `@onekeyfe/shared` HardwareErrorCode (which occupies 0-902).\n *\n * All HWK codes are 5-digit (>= 10000) so the two tables never collide\n * even if either side grows. Each sub-category gets a 100-slot block.\n *\n * 10000-10099 Generic / cross-cutting primitives\n * 10100-10199 Device state\n * 10200-10299 Firmware\n * 10300-10399 Transport + OS-level permission\n * 10400-10499 PIN / Passphrase\n * 10500-10599 App lifecycle (wrong app, not open, too old)\n * 10600-10999 RESERVED — future adapter-level categories\n *\n * 11000-11099 EVM APDU (reactive mapping)\n * 11100-11199 Solana APDU\n * 11200-11299 Tron APDU\n * 11300-11399 BTC APDU\n * 11400-11999 RESERVED — future chain APDU blocks (100 per chain)\n *\n * 12000-99999 RESERVED — future major categories\n */\nexport enum HardwareErrorCode {\n // --- 10000s Generic ---\n UnknownError = 10000,\n UserRejected = 10001,\n InvalidParams = 10002,\n OperationTimeout = 10003,\n MethodNotSupported = 10004,\n /** User dismissed in-app cancel UI. Distinct from UserRejected (on-device). */\n UserAborted = 10005,\n\n // --- 10100s Device state ---\n DeviceNotFound = 10100,\n DeviceDisconnected = 10101,\n DeviceBusy = 10102,\n DeviceLocked = 10103,\n DeviceNotInitialized = 10104,\n DeviceInBootloader = 10105,\n DeviceMismatch = 10106,\n /** Chain app wedged (e.g. Ledger BTC 0x6901). User must exit app on device. */\n DeviceAppStuck = 10107,\n /** Vendor (Ledger / Trezor) doesn't support the chain at all. */\n ChainNotSupported = 10108,\n /** Current operation supports only one connected device. */\n DeviceOneDeviceOnly = 10109,\n\n // --- 10200s Firmware ---\n FirmwareTooOld = 10200,\n FirmwareUpdateRequired = 10201,\n\n // --- 10300s Transport + permission ---\n TransportError = 10300,\n BridgeNotFound = 10301,\n TransportNotAvailable = 10302,\n /**\n * OS-level permission (Bluetooth / USB / etc.) — denied, blocked,\n * unavailable, or dismissed. Consumers surface a single \"please grant\n * permission\" toast and let the user retry manually.\n */\n DevicePermissionDenied = 10303,\n /**\n * BLE SMP pairing did not complete within the GATT bonding window.\n * GATT connected but the device didn't acknowledge SMP — typically\n * because the user didn't confirm the passkey on the device, or the\n * device went out of range mid-pairing. Distinct from OperationTimeout\n * (generic) and from DeviceLocked (Secure Element actually locked).\n */\n BlePairingTimeout = 10304,\n\n // --- 10400s PIN / Passphrase ---\n PinInvalid = 10400,\n PinCancelled = 10401,\n PassphraseRejected = 10402,\n\n // --- 10500s App lifecycle ---\n /** Chain app NOT INSTALLED on device. User must install via Ledger Live. */\n AppNotInstalled = 10500,\n WrongApp = 10501,\n /** 0x911c Command code not supported — app predates current SDK. */\n AppTooOld = 10502,\n /** Not enough free storage for install/update; user must uninstall apps first. */\n DeviceOutOfMemory = 10503,\n\n // --- 11000s EVM (Ledger Ethereum App) APDU-specific ---\n /** 0x6a80 Invalid data — observed on blindSignTransactionFallback when the\n * user has not enabled Blind signing on the device. */\n EvmBlindSigningRequired = 11000,\n /** 0x6984 Plugin not installed */\n EvmClearSignPluginMissing = 11001,\n /** 0x6a84 Insufficient memory (typical on Nano S with large calldata) */\n EvmDataTooLarge = 11002,\n /** 0x6501 TransactionType not supported (app too old for EIP-1559 / blob / 7702) */\n EvmTxTypeNotSupported = 11003,\n\n // --- 11100s Solana ---\n /** 0x6808 Blind signing disabled for this instruction. */\n SolanaBlindSigningRequired = 11100,\n\n // --- 11200s Tron ---\n /** 0x6a8d Custom Contracts setting disabled (blocks TRC-20 etc.). */\n TronCustomContractRequired = 11200,\n /** 0x6a8b Transactions Data setting disabled. */\n TronDataSigningRequired = 11201,\n /** 0x6a8c Sign by Hash setting disabled (hash-signing fallback). */\n TronSignByHashRequired = 11202,\n\n // --- 11300s BTC ---\n /** 0xb008 Wallet policy HMAC mismatch or not registered. */\n BtcWalletPolicyHmacMismatch = 11300,\n /** 0xb007 Aborted due to unexpected state (malformed PSBT / missing UTXO). */\n BtcUnexpectedState = 11301,\n}\n\n/**\n * Device-level failures the SDK cannot self-recover from — affect the entire\n * batch (vs per-chain failures like AppNotInstalled / WrongApp which soft-\n * skip in onboarding). Combined with `accounts.length === 0`, signals\n * genuine orphan. Also reused as the batch-abort whitelist for HWK.\n * Single source of truth.\n *\n * UserRejected (device-side reject) is included: pressing reject is an\n * explicit \"I don't consent\" — continuing the batch to ask again on the\n * next chain is harassment, not helpful.\n */\nexport const ORPHAN_ELIGIBLE_ERROR_CODES: number[] = [\n HardwareErrorCode.UserAborted,\n HardwareErrorCode.UserRejected,\n HardwareErrorCode.DeviceNotFound,\n HardwareErrorCode.DeviceDisconnected,\n HardwareErrorCode.DeviceMismatch,\n HardwareErrorCode.DeviceAppStuck,\n HardwareErrorCode.DeviceOneDeviceOnly,\n HardwareErrorCode.TransportError,\n HardwareErrorCode.DevicePermissionDenied,\n HardwareErrorCode.BlePairingTimeout,\n];\n","import type { HardwareErrorCode } from './errors';\n\nexport interface Success<T> {\n success: true;\n payload: T;\n}\n\nexport interface Failure {\n success: false;\n payload: {\n error: string;\n code: HardwareErrorCode;\n params?: Record<string, unknown>;\n };\n}\n\nexport type Response<T> = Success<T> | Failure;\n\nexport function success<T>(payload: T): Success<T> {\n return { success: true, payload };\n}\n\nexport function failure(\n code: HardwareErrorCode,\n error: string,\n params?: Record<string, unknown>\n): Failure {\n return {\n success: false,\n payload: { error, code, ...(params ? { params } : {}) },\n };\n}\n","/**\n * Chain fingerprint utilities for device identity verification.\n *\n * Ledger devices have ephemeral IDs that change every session.\n * To verify that the same seed/device is connected, we derive an address\n * at a fixed path (account 0, index 0) and hash it into a stable \"chain fingerprint\".\n */\nimport { sha256 } from '@noble/hashes/sha256';\nimport { bytesToHex, utf8ToBytes } from '@noble/hashes/utils';\n\n/**\n * Fixed derivation paths used to generate chain fingerprints.\n * Uses standard index 0 — Ledger firmware shows device confirmation for\n * non-standard paths (e.g., index=100), which would interrupt wallet creation.\n * The address is hashed into a 16-char fingerprint, not exposed directly.\n * - EVM: cointype 60 (Ledger ETH App only supports 60)\n * - BTC: cointype 1 (testnet)\n * - SOL: cointype 501, standard 3-level hardened\n */\nexport const CHAIN_FINGERPRINT_PATHS: Record<ChainForFingerprint, string> = {\n evm: \"m/44'/60'/0'/0/0\",\n // BTC: account-level path (3 levels), mainnet cointype 0.\n // Cointype 1 (testnet) is rejected by some Ledger BTC App configurations.\n btc: \"m/44'/0'/0'\",\n sol: \"m/44'/501'/0'\",\n tron: \"m/44'/195'/0'/0/0\",\n};\n\nexport type ChainForFingerprint = 'evm' | 'btc' | 'sol' | 'tron';\n\n/**\n * 16-char SHA-256 fingerprint for device-identity verification.\n * Callers must canonicalize input (e.g. EVM address → lowercase) —\n * encoding variations otherwise cause false DeviceMismatch.\n */\nexport function deriveDeviceFingerprint(value: string): string {\n return bytesToHex(sha256(utf8ToBytes(value))).slice(0, 16);\n}\n","export const DEVICE_EVENT = 'DEVICE_EVENT';\n\n/** Events originating from the hardware device. */\nexport const DEVICE = {\n CONNECT: 'device-connect',\n DISCONNECT: 'device-disconnect',\n CHANGED: 'device-changed',\n} as const;\n","import type { QrResponseData } from '../types/qr';\n\nexport const UI_EVENT = 'UI_EVENT';\n\nexport const UI_REQUEST = {\n REQUEST_PIN: 'ui-request-pin',\n REQUEST_PASSPHRASE: 'ui-request-passphrase',\n REQUEST_PASSPHRASE_ON_DEVICE: 'ui-request-passphrase-on-device',\n REQUEST_BUTTON: 'ui-request-button',\n REQUEST_QR_DISPLAY: 'ui-request-qr-display',\n REQUEST_QR_SCAN: 'ui-request-qr-scan',\n REQUEST_DEVICE_PERMISSION: 'ui-request-device-permission',\n REQUEST_SELECT_DEVICE: 'ui-request-select-device',\n REQUEST_DEVICE_CONNECT: 'ui-request-device-connect',\n // Ledger BTC App: account index >= 100 requires display=true. Adapter asks\n // the user once per session before promoting the call.\n REQUEST_BTC_HIGH_INDEX_CONFIRM: 'ui-request-btc-high-index-confirm',\n // Required app is not installed; with autoInstallApp on, ask the user\n // whether to install it before retrying the operation.\n REQUEST_INSTALL_APP: 'ui-request-install-app',\n CLOSE_UI_WINDOW: 'ui-close',\n DEVICE_PROGRESS: 'ui-device_progress',\n FIRMWARE_PROGRESS: 'ui-firmware-progress',\n FIRMWARE_TIP: 'ui-firmware-tip',\n} as const;\n\nexport const UI_RESPONSE = {\n RECEIVE_PIN: 'receive-pin',\n RECEIVE_PASSPHRASE: 'receive-passphrase',\n RECEIVE_PASSPHRASE_ON_DEVICE: 'receive-passphrase-on-device',\n RECEIVE_QR_RESPONSE: 'receive-qr-response',\n RECEIVE_SELECT_DEVICE: 'receive-select-device',\n RECEIVE_DEVICE_CONNECT: 'receive-device-connect',\n RECEIVE_DEVICE_PERMISSION: 'receive-device-permission',\n RECEIVE_BTC_HIGH_INDEX_CONFIRM: 'receive-btc-high-index-confirm',\n RECEIVE_INSTALL_APP: 'receive-install-app',\n CANCEL: 'cancel',\n} as const;\n\nexport type DevicePermissionDeniedReason =\n | 'bluetoothTurnedOff'\n | 'permissionDenied'\n | (string & Record<never, never>);\n\nexport type DevicePermissionResponse = {\n granted: boolean;\n reason?: DevicePermissionDeniedReason;\n message?: string;\n};\n\nexport type UiResponseEvent =\n | {\n type: typeof UI_RESPONSE.RECEIVE_PIN;\n payload: string;\n }\n | {\n type: typeof UI_RESPONSE.RECEIVE_PASSPHRASE;\n payload: {\n value: string;\n passphraseOnDevice?: boolean;\n save?: boolean;\n };\n }\n | {\n type: typeof UI_RESPONSE.RECEIVE_PASSPHRASE_ON_DEVICE;\n payload?: undefined;\n }\n | {\n type: typeof UI_RESPONSE.RECEIVE_QR_RESPONSE;\n payload: QrResponseData;\n }\n | {\n // sdkConnectId echoes one of the DeviceInfo.connectId values emitted in\n // the REQUEST_SELECT_DEVICE event's `devices` list. Scope is the current\n // search session; may be ephemeral (e.g. Ledger USB DMK UUID).\n type: typeof UI_RESPONSE.RECEIVE_SELECT_DEVICE;\n payload: { sdkConnectId: string };\n }\n | {\n type: typeof UI_RESPONSE.RECEIVE_DEVICE_CONNECT;\n payload: { confirmed: boolean };\n }\n | {\n type: typeof UI_RESPONSE.RECEIVE_DEVICE_PERMISSION;\n payload: DevicePermissionResponse;\n }\n | {\n type: typeof UI_RESPONSE.RECEIVE_BTC_HIGH_INDEX_CONFIRM;\n payload: { confirmed: boolean };\n }\n | {\n type: typeof UI_RESPONSE.RECEIVE_INSTALL_APP;\n payload: { confirmed: boolean };\n }\n | {\n type: typeof UI_RESPONSE.CANCEL;\n payload?: undefined;\n };\n","/** Events generated by SDK internal detection (not from hardware directly). */\nexport const SDK = {\n DEVICE_STUCK: 'device-stuck',\n DEVICE_UNRESPONSIVE: 'device-unresponsive',\n DEVICE_RECOVERED: 'device-recovered',\n DEVICE_INTERACTION: 'device-interaction',\n} as const;\n","/**\n * Pure FIFO job queue. Every enqueue chains onto the tail; jobs run one at\n * a time across all devices. The queue is intentionally passive — it does\n * NOT decide whether to interrupt or ask the user. Those are application-\n * layer concerns owned by the caller (e.g. a UI button handler that wants\n * to ask \"device is busy, interrupt current?\" before submitting). The\n * queue exposes inspection (`getActiveJob`) and explicit cancellation\n * (`cancelActive` / `cancelAll`) so callers can implement those policies\n * synchronously, without racing against in-flight enqueues.\n */\n\nexport interface JobOptions {\n label?: string;\n rejectIfBusy?: boolean;\n busyError?: Error;\n}\n\nexport interface ActiveJobInfo {\n deviceId: string;\n label?: string;\n startedAt: number;\n}\n\ninterface ActiveJob {\n deviceId: string;\n label?: string;\n abortController: AbortController;\n startedAt: number;\n}\n\nexport class DeviceJobQueue {\n private _tail: Promise<unknown> = Promise.resolve();\n\n private _active: ActiveJob | null = null;\n\n private readonly _jobs = new Map<object, { deviceId: string }>();\n\n /** Incremented on clear() so queued-but-not-yet-running jobs detect invalidation. */\n private _generation = 0;\n\n private readonly _generationCancelReasons = new Map<number, Error>();\n\n /**\n * Enqueue a job. Runs after every previously-enqueued job has settled.\n * `deviceId` is a label only — used by inspection / cancellation routing.\n */\n async enqueue<T>(\n deviceId: string,\n job: (signal: AbortSignal) => Promise<T>,\n options: JobOptions = {}\n ): Promise<T> {\n if (options.rejectIfBusy && this._jobs.size > 0) {\n throw options.busyError ?? new Error('Device is busy');\n }\n\n const ac = new AbortController();\n const gen = this._generation;\n const prev = this._tail;\n const jobToken = {};\n const activeJob: ActiveJob = {\n deviceId,\n label: options.label,\n abortController: ac,\n startedAt: Date.now(),\n };\n this._jobs.set(jobToken, { deviceId });\n\n const next = prev\n .catch(() => {})\n .then(async () => {\n if (this._generation !== gen) {\n throw (\n this._generationCancelReasons.get(gen) ?? new Error('Job cancelled: queue was cleared')\n );\n }\n this._active = activeJob;\n try {\n return await job(ac.signal);\n } finally {\n // Identity guard: a previous job's deferred finally must not\n // null out a successor's `_active`.\n if (this._active === activeJob) {\n this._active = null;\n }\n }\n })\n .finally(() => {\n this._jobs.delete(jobToken);\n });\n\n this._tail = next.catch(() => {});\n return next;\n }\n\n /** Cancel the active job. If `deviceId` is given, only cancels when it matches. */\n cancelActive(deviceId?: string): boolean {\n if (!this._active) return false;\n if (deviceId && this._active.deviceId !== deviceId) return false;\n this._active.abortController.abort(new Error('Manually cancelled'));\n return true;\n }\n\n /** Force cancel the active job. `reason` becomes signal.reason. */\n forceCancelActive(deviceId?: string, reason?: Error): boolean {\n if (!this._active) return false;\n if (deviceId && this._active.deviceId !== deviceId) return false;\n this._active.abortController.abort(reason ?? new Error('Force cancelled for recovery'));\n return true;\n }\n\n /** Cancel the active job (alias for callers that previously needed multi-device cancel). */\n cancelAllActive(reason?: Error): void {\n if (!this._active) return;\n this._active.abortController.abort(reason ?? new Error('Cancelled by cancelAllActive'));\n }\n\n /** Cancel the active job and invalidate queued jobs that have not started. */\n cancelActiveAndPending(deviceId?: string, reason?: Error): boolean {\n if (deviceId && this._active && this._active.deviceId !== deviceId) {\n return false;\n }\n this.clear(reason ?? new Error('Cancelled by cancelActiveAndPending'));\n return true;\n }\n\n /** Get info about the currently active job, or null if idle. */\n getActiveJob(deviceId?: string): ActiveJobInfo | null {\n if (!this._active) return null;\n if (deviceId && this._active.deviceId !== deviceId) return null;\n return {\n deviceId: this._active.deviceId,\n label: this._active.label,\n startedAt: this._active.startedAt,\n };\n }\n\n /** True if any job is currently running. */\n isBusy(): boolean {\n return this._jobs.size > 0;\n }\n\n clear(reason?: Error): void {\n const cancelledGeneration = this._generation;\n this._generation++;\n const cancelReason = reason ?? new Error('Job cancelled: queue was cleared');\n this._generationCancelReasons.set(cancelledGeneration, cancelReason);\n for (const generation of this._generationCancelReasons.keys()) {\n if (generation < this._generation - 10) {\n this._generationCancelReasons.delete(generation);\n }\n }\n if (this._active) {\n this._active.abortController.abort(cancelReason);\n }\n }\n}\n","import type { ConnectionType, DeviceCapabilities, DeviceInfo, VendorType } from './device';\nimport type { UiResponseEvent } from '../events/ui-request';\n\n// =====================================================================\n// Connector types — transport-level abstraction for device communication\n// =====================================================================\n\n/**\n * Minimal device info returned during discovery (searchDevices).\n * At scan time, full DeviceInfo fields like firmwareVersion are not yet available.\n */\nexport interface ConnectorDevice {\n connectId: string;\n deviceId: string;\n name: string;\n /** Machine model id (e.g. \"nanoX\"). */\n model?: string;\n /** Human-readable model name (e.g. \"Ledger Nano X\"). */\n modelName?: string;\n /** BLE signal strength (BLE only). */\n rssi?: number | null;\n /** BLE connectable flag (BLE only). */\n isConnectable?: boolean | null;\n /** USB serial number (USB only). */\n serialNumber?: string;\n\n /** Device capabilities — available from scan time */\n capabilities?: DeviceCapabilities;\n}\n\nexport interface ConnectorSession {\n sessionId: string;\n deviceInfo: DeviceInfo;\n}\n\n// =====================================================================\n// Connector call result — device errors travel as DATA, not exceptions\n//\n// `IConnector.call` never throws for device-level failures. It resolves a\n// discriminated result so the failure crosses any process boundary\n// (IHardwareBridge / extension offscreen↔SW) as plain `data`. This mirrors\n// the OneKey HD-SDK `IDeviceResponseResult` contract.\n//\n// WHY: when a thrown Error crosses the extension JsBridge it is run through\n// `toPlainError`, a fixed field whitelist that drops custom own-properties\n// (e.g. `appName`). Returning the failure as data keeps every field intact.\n//\n// Contract for `ConnectorSerializedError`: only `message` / `code` /\n// `errorCode` live at the top level; ALL other domain fields (`appName`,\n// `_tag`, `statusCode`, …) are nested under `params`.\n// =====================================================================\n\n/**\n * Vendor-agnostic bag of extra error fields. Known keys are documented for\n * discoverability; the index signature keeps it open so any connector can\n * carry vendor-specific data without losing it across the bridge.\n */\nexport interface ConnectorErrorParams {\n /** Vendor SDK error tag (e.g. Ledger DMK `_tag`). */\n _tag?: string;\n /** App involved, e.g. the Ledger app being opened/installed. */\n appName?: string;\n /** Transport / APDU status code (string or number depending on vendor). */\n statusCode?: unknown;\n /**\n * Shallow snapshot of a nested cause. A raw Error does not survive JSON\n * serialization (its `message`/`stack` are non-enumerable), so recovery\n * predicates that recurse into a cause get this plain-object copy instead.\n */\n originalError?: {\n message?: string;\n code?: number;\n errorCode?: string;\n statusCode?: unknown;\n _tag?: string;\n };\n [key: string]: unknown;\n}\n\nexport interface ConnectorSerializedError {\n message: string;\n code?: number;\n errorCode?: string;\n params?: ConnectorErrorParams;\n}\n\nexport type ConnectorCallResult =\n | { success: true; payload: unknown }\n | { success: false; error: ConnectorSerializedError };\n\nexport type ConnectorEventType = 'device-connect' | 'device-disconnect' | 'ui-request' | 'ui-event';\n\n/**\n * Interaction event types emitted via 'ui-event'.\n * These map to user-facing prompts (confirm on device, open app, etc.).\n */\nexport enum EConnectorInteraction {\n /** Adapter is actively searching for the device (no session yet) */\n Searching = 'searching',\n /** Device requires user to open a specific app */\n ConfirmOpenApp = 'confirm-open-app',\n /** Device requires user to unlock */\n UnlockDevice = 'unlock-device',\n /** Device needs user to confirm on device (sign, verify, etc.) */\n ConfirmOnDevice = 'confirm-on-device',\n /** Previous interaction completed — clear UI prompt */\n InteractionComplete = 'interaction-complete',\n /**\n * OS-level Ledger app install progress. `progress` is a 0..1 fraction\n * reported by DMK's InstallOrUpdateAppsDeviceAction. Emitted from inside\n * the connector so the progress callback ref never has to cross the\n * IHardwareBridge boundary.\n */\n AppInstallProgress = 'app-install-progress',\n}\n\n// Discriminated union: most variants only carry `sessionId`, but\n// AppInstallProgress also carries `appName` + `progress`. Searching has no\n// session yet so it carries an empty `sessionId`.\nexport type ConnectorUiEvent =\n | { type: EConnectorInteraction.Searching; payload: { sessionId: string } }\n | { type: EConnectorInteraction.ConfirmOpenApp; payload: { sessionId: string } }\n | { type: EConnectorInteraction.UnlockDevice; payload: { sessionId: string } }\n | { type: EConnectorInteraction.ConfirmOnDevice; payload: { sessionId: string } }\n | { type: EConnectorInteraction.InteractionComplete; payload: { sessionId: string } }\n | {\n type: EConnectorInteraction.AppInstallProgress;\n payload: { sessionId: string; appName: string; progress: number };\n };\n\nexport interface ConnectorEventMap {\n 'device-connect': { device: ConnectorDevice };\n 'device-disconnect': { connectId: string };\n 'ui-request': { type: string; payload?: unknown };\n 'ui-event': ConnectorUiEvent;\n}\n\nexport interface IConnector {\n /** Physical connection type this connector uses. Fixed at construction. */\n readonly connectionType: ConnectionType;\n\n searchDevices(): Promise<ConnectorDevice[]>;\n connect(deviceId?: string): Promise<ConnectorSession>;\n disconnect(sessionId: string): Promise<void>;\n // `call` resolves a discriminated result; device-level failures are returned\n // as data, never thrown (see ConnectorCallResult). Only `call` uses this\n // contract because it is the one method that carries rich, vendor-specific\n // domain errors across the IHardwareBridge boundary, where a thrown Error\n // would be stripped by the host bridge's error whitelist. The other methods\n // surface plain operational failures and still reject normally.\n call(sessionId: string, method: string, params: unknown): Promise<ConnectorCallResult>;\n cancel(sessionId: string): Promise<void>;\n\n /** Send a UI response (e.g. PIN, passphrase) to the device. */\n uiResponse(response: UiResponseEvent): void;\n\n on<K extends ConnectorEventType>(event: K, handler: (data: ConnectorEventMap[K]) => void): void;\n off<K extends ConnectorEventType>(event: K, handler: (data: ConnectorEventMap[K]) => void): void;\n\n reset(): void;\n}\n\n// =====================================================================\n// Hardware bridge — generic forwarding interface for cross-boundary IConnector\n//\n// The same shape works across any process / context boundary that needs to\n// expose a multi-vendor backend behind a single-vendor IConnector facade:\n// - Electron (renderer ↔ preload/main via contextBridge)\n// - Browser Extension (popup/content ↔ background/offscreen via chrome.runtime)\n// - React Native (JS ↔ native module via NativeModules)\n// - Web Worker / iframe (postMessage)\n//\n// Each method takes a `vendor` discriminator so a single bridge implementation\n// can multiplex across vendors (ledger, trezor, ...).\n// =====================================================================\n\nexport interface IHardwareBridge {\n searchDevices(params: { vendor: VendorType }): Promise<ConnectorDevice[]>;\n connect(params: { vendor: VendorType; deviceId?: string }): Promise<ConnectorSession>;\n disconnect(params: { vendor: VendorType; sessionId: string }): Promise<void>;\n call(params: {\n vendor: VendorType;\n sessionId: string;\n method: string;\n callParams: unknown;\n }): Promise<ConnectorCallResult>;\n cancel(params: { vendor: VendorType; sessionId: string }): Promise<void>;\n uiResponse(params: { vendor: VendorType; response: UiResponseEvent }): void;\n reset(params: { vendor: VendorType }): void;\n\n /** Register an event handler for connector events forwarded across the bridge. */\n onEvent(\n params: { vendor: VendorType },\n handler: (event: { type: ConnectorEventType; data: unknown }) => void\n ): void;\n\n /** Unregister a previously registered event handler. */\n offEvent(\n params: { vendor: VendorType },\n handler: (event: { type: ConnectorEventType; data: unknown }) => void\n ): void;\n}\n\n/**\n * Adapt an IHardwareBridge (multi-vendor backend) into a single-vendor IConnector.\n * Every IConnector method becomes a transparent forward to bridge.<method>({ vendor, ... }).\n * Events are forwarded via bridge.onEvent / offEvent.\n *\n * Use this anywhere the actual hardware lives behind a process / context boundary\n * (Electron main, extension background, native module, worker, iframe).\n */\nexport function createBridgedConnector(\n vendor: VendorType,\n connectionType: ConnectionType,\n bridge: IHardwareBridge\n): IConnector {\n // Keyed by (event, handler). A flat handler-only map would collide when the\n // same function is registered for multiple events — second .on() would\n // overwrite the first bridge handler reference, leaking it permanently.\n type UserHandler = (data: ConnectorEventMap[ConnectorEventType]) => void;\n type BridgeHandler = (event: { type: ConnectorEventType; data: unknown }) => void;\n const handlerMap = new Map<ConnectorEventType, Map<UserHandler, BridgeHandler>>();\n\n return {\n connectionType,\n searchDevices: () => bridge.searchDevices({ vendor }),\n connect: deviceId => bridge.connect({ vendor, deviceId }),\n disconnect: sessionId => bridge.disconnect({ vendor, sessionId }),\n call: (sessionId, method, callParams) => bridge.call({ vendor, sessionId, method, callParams }),\n cancel: sessionId => bridge.cancel({ vendor, sessionId }),\n uiResponse: response => bridge.uiResponse({ vendor, response }),\n on: (event, handler) => {\n const bridgeHandler: BridgeHandler = e => {\n if (e.type === event) {\n handler(e.data as ConnectorEventMap[typeof event]);\n }\n };\n let inner = handlerMap.get(event);\n if (!inner) {\n inner = new Map();\n handlerMap.set(event, inner);\n }\n inner.set(handler as UserHandler, bridgeHandler);\n bridge.onEvent({ vendor }, bridgeHandler);\n },\n off: (event, handler) => {\n const inner = handlerMap.get(event);\n const bridgeHandler = inner?.get(handler as UserHandler);\n if (!bridgeHandler || !inner) return;\n bridge.offEvent({ vendor }, bridgeHandler);\n inner.delete(handler as UserHandler);\n if (inner.size === 0) handlerMap.delete(event);\n },\n reset: () => bridge.reset({ vendor }),\n };\n}\n\n// =====================================================================\n// ConnectorCallResult error (de)serialization — the canonical, vendor-agnostic\n// helpers every IConnector implementation / adapter should use, so the\n// \"errors as data\" contract is identical across vendors.\n// =====================================================================\n\nconst SERIALIZED_ERROR_TOP_LEVEL_KEYS = new Set([\n 'message',\n 'code',\n 'errorCode',\n 'stack',\n 'params',\n]);\n\n/**\n * Flatten a thrown error into the cross-boundary-safe `ConnectorSerializedError`\n * shape. `message`/`code`/`errorCode` are lifted to the top level; every other\n * own-enumerable field is copied into `params` so NO domain data is lost when\n * the result crosses a host bridge (which may run thrown errors through a\n * field whitelist). A nested `originalError` is shallow-snapshotted because a\n * raw Error does not survive JSON serialization.\n */\nexport function serializeConnectorError(err: unknown): ConnectorSerializedError {\n if (!err || typeof err !== 'object') {\n return { message: typeof err === 'string' ? err : 'Unknown error' };\n }\n const e = err as Record<string, unknown>;\n const message = typeof e.message === 'string' ? e.message : 'Unknown error';\n const code = typeof e.code === 'number' ? e.code : undefined;\n const errorCode = e.errorCode != null ? String(e.errorCode) : undefined;\n\n const params: ConnectorErrorParams = {};\n // Flatten an existing `params` bag, then copy every other own field (so\n // vendor-specific keys like `_tag` / `statusCode` / `appName` / step context\n // are preserved without being named here).\n if (e.params && typeof e.params === 'object') {\n Object.assign(params, e.params as Record<string, unknown>);\n }\n for (const key of Object.keys(e)) {\n if (!SERIALIZED_ERROR_TOP_LEVEL_KEYS.has(key)) {\n params[key] = e[key];\n }\n }\n const orig = e.originalError;\n if (orig && typeof orig === 'object') {\n const o = orig as Record<string, unknown>;\n params.originalError = {\n message: typeof o.message === 'string' ? o.message : undefined,\n code: typeof o.code === 'number' ? o.code : undefined,\n errorCode: o.errorCode != null ? String(o.errorCode) : undefined,\n statusCode: o.statusCode,\n _tag: typeof o._tag === 'string' ? o._tag : undefined,\n };\n }\n\n // The result crosses host bridges via JSON.stringify. Drop any single field\n // that isn't JSON-safe (circular ref / non-serializable) so a pathological\n // error degrades to \"one field missing\" instead of crashing the transport.\n for (const key of Object.keys(params)) {\n try {\n JSON.stringify(params[key]);\n } catch {\n delete params[key];\n }\n }\n\n return {\n message,\n ...(code !== undefined ? { code } : {}),\n ...(errorCode !== undefined ? { errorCode } : {}),\n ...(Object.keys(params).length ? { params } : {}),\n };\n}\n\n/**\n * Inverse of `serializeConnectorError`: rebuild a flat Error instance, lifting\n * `params.*` back to own-properties so existing throw-based classifiers/recovery\n * logic (which read `err._tag` / `err.code` / `err.appName` / …) keep working\n * unchanged. The Result shape stays confined to the connector boundary.\n */\nexport function rehydrateConnectorError(error: ConnectorSerializedError): Error {\n const { message, code, errorCode, params } = error;\n return Object.assign(new Error(message), {\n ...(code !== undefined ? { code } : {}),\n ...(errorCode !== undefined ? { errorCode } : {}),\n ...(params ?? {}),\n });\n}\n","/**\n * Minimal typed event emitter using Map<string, Set<listener>>.\n * Each adapter uses this for device events (connect, disconnect, pin, etc.).\n *\n * TMap is a record mapping event name strings to their payload types.\n * Example:\n * type MyEvents = { 'connect': { id: string }; 'disconnect': { id: string } };\n * const emitter = new TypedEventEmitter<MyEvents>();\n * emitter.on('connect', (data) => { data.id }); // data is { id: string }\n *\n * For backward compatibility, TMap defaults to Record<string, any> so that\n * existing code using `new TypedEventEmitter<SomeUnionType>()` still compiles.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport class TypedEventEmitter<TMap extends Record<string, any> = Record<string, any>> {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private readonly _listeners = new Map<string, Set<(event: any) => void>>();\n\n on<K extends keyof TMap & string>(event: K, listener: (event: TMap[K]) => void): void;\n\n on(event: string, listener: (event: any) => void): void;\n\n on(event: string, listener: (event: any) => void): void {\n let set = this._listeners.get(event);\n if (!set) {\n set = new Set();\n this._listeners.set(event, set);\n }\n set.add(listener);\n }\n\n off<K extends keyof TMap & string>(event: K, listener: (event: TMap[K]) => void): void;\n\n off(event: string, listener: (event: any) => void): void;\n\n off(event: string, listener: (event: any) => void): void {\n const set = this._listeners.get(event);\n if (set) {\n set.delete(listener);\n if (set.size === 0) this._listeners.delete(event);\n }\n }\n\n emit<K extends keyof TMap & string>(event: K, data: TMap[K]): void;\n\n emit(event: string, data: unknown): void;\n\n emit(event: string, data: unknown): void {\n const set = this._listeners.get(event);\n if (set) {\n for (const listener of set) listener(data);\n }\n }\n\n removeAllListeners(): void {\n this._listeners.clear();\n }\n}\n","import { UI_REQUEST, UI_RESPONSE } from '../events/ui-request';\n\n/** 10 min — every UI request is human-in-the-loop; bias toward \"wait long\". */\nexport const UI_REQUEST_DEFAULT_TIMEOUT_MS = 600_000;\n\nconst RESPONSE_TO_REQUEST: Record<string, string> = {\n [UI_RESPONSE.RECEIVE_PIN]: UI_REQUEST.REQUEST_PIN,\n [UI_RESPONSE.RECEIVE_PASSPHRASE]: UI_REQUEST.REQUEST_PASSPHRASE,\n [UI_RESPONSE.RECEIVE_PASSPHRASE_ON_DEVICE]: UI_REQUEST.REQUEST_PASSPHRASE_ON_DEVICE,\n [UI_RESPONSE.RECEIVE_SELECT_DEVICE]: UI_REQUEST.REQUEST_SELECT_DEVICE,\n [UI_RESPONSE.RECEIVE_DEVICE_CONNECT]: UI_REQUEST.REQUEST_DEVICE_CONNECT,\n [UI_RESPONSE.RECEIVE_DEVICE_PERMISSION]: UI_REQUEST.REQUEST_DEVICE_PERMISSION,\n [UI_RESPONSE.RECEIVE_BTC_HIGH_INDEX_CONFIRM]: UI_REQUEST.REQUEST_BTC_HIGH_INDEX_CONFIRM,\n [UI_RESPONSE.RECEIVE_INSTALL_APP]: UI_REQUEST.REQUEST_INSTALL_APP,\n // RECEIVE_QR_RESPONSE maps to QR_DISPLAY or QR_SCAN — resolved dynamically below.\n};\n\nexport const UI_REQUEST_PREEMPTED_TAG = 'UiRequestPreempted';\nexport const UI_REQUEST_CANCELLED_TAG = 'UiRequestCancelled';\nexport const UI_REQUEST_TIMEOUT_TAG = 'UiRequestTimeout';\n\ntype PendingEntry = {\n resolve: (payload: unknown) => void;\n reject: (error: Error) => void;\n timer: ReturnType<typeof setTimeout>;\n};\n\n/**\n * Per-type single-slot registry for adapter-level UI requests. A new `wait`\n * of the same type supersedes (rejects) the prior pending entry. With the\n * job queue running globally serially, cross-type collisions don't occur in\n * normal flow — same-type preemption is a defensive measure for callers\n * that fire the same request twice without waiting on the first.\n *\n * Unknown response types are dropped silently so the public `uiResponse`\n * entry never throws.\n */\nexport class UiRequestRegistry {\n private pending = new Map<string, PendingEntry>();\n\n wait<T = unknown>(requestType: string, options?: { timeoutMs?: number }): Promise<T> {\n const existing = this.pending.get(requestType);\n if (existing) {\n clearTimeout(existing.timer);\n this.pending.delete(requestType);\n existing.reject(\n Object.assign(new Error(`UI request '${requestType}' was superseded by a new request`), {\n _tag: UI_REQUEST_PREEMPTED_TAG,\n })\n );\n }\n\n const timeoutMs = options?.timeoutMs ?? UI_REQUEST_DEFAULT_TIMEOUT_MS;\n\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => {\n if (this.pending.get(requestType)?.timer === timer) {\n this.pending.delete(requestType);\n reject(\n Object.assign(new Error(`UI request '${requestType}' timed out after ${timeoutMs}ms`), {\n _tag: UI_REQUEST_TIMEOUT_TAG,\n })\n );\n }\n }, timeoutMs);\n\n this.pending.set(requestType, {\n resolve: resolve as (payload: unknown) => void,\n reject,\n timer,\n });\n });\n }\n\n resolve(responseType: string, payload: unknown): void {\n let requestType = RESPONSE_TO_REQUEST[responseType];\n if (responseType === UI_RESPONSE.RECEIVE_QR_RESPONSE) {\n if (this.pending.has(UI_REQUEST.REQUEST_QR_DISPLAY)) {\n requestType = UI_REQUEST.REQUEST_QR_DISPLAY;\n } else if (this.pending.has(UI_REQUEST.REQUEST_QR_SCAN)) {\n requestType = UI_REQUEST.REQUEST_QR_SCAN;\n }\n }\n if (!requestType) return;\n\n const entry = this.pending.get(requestType);\n if (!entry) return;\n\n clearTimeout(entry.timer);\n this.pending.delete(requestType);\n entry.resolve(payload);\n }\n\n cancel(requestType?: string): void {\n if (requestType) {\n const entry = this.pending.get(requestType);\n if (!entry) return;\n clearTimeout(entry.timer);\n this.pending.delete(requestType);\n entry.reject(\n Object.assign(new Error(`UI request '${requestType}' was cancelled`), {\n _tag: UI_REQUEST_CANCELLED_TAG,\n })\n );\n return;\n }\n\n for (const [type, entry] of this.pending) {\n clearTimeout(entry.timer);\n entry.reject(\n Object.assign(new Error(`UI request '${type}' was cancelled`), {\n _tag: UI_REQUEST_CANCELLED_TAG,\n })\n );\n }\n this.pending.clear();\n }\n\n reset(): void {\n this.cancel();\n }\n\n hasPending(requestType?: string): boolean {\n if (requestType) return this.pending.has(requestType);\n return this.pending.size > 0;\n }\n}\n","/**\n * Compare two semver strings (e.g. \"2.1.0\" vs \"2.3.1\").\n * Returns -1 if a < b, 0 if equal, 1 if a > b.\n */\nexport function compareSemver(a: string, b: string): number {\n const pa = a.split('.').map(Number);\n const pb = b.split('.').map(Number);\n for (let i = 0; i < 3; i++) {\n const va = pa[i] ?? 0;\n const vb = pb[i] ?? 0;\n if (va < vb) return -1;\n if (va > vb) return 1;\n }\n return 0;\n}\n","import { bytesToHex as nobleBytesToHex, hexToBytes as nobleHexToBytes } from '@noble/hashes/utils';\n\n/** Ensure hex string has 0x prefix */\nexport function ensure0x(hex: string): string {\n return hex.startsWith('0x') ? hex : `0x${hex}`;\n}\n\n/** Strip 0x prefix from hex string */\nexport function stripHex(hex: string): string {\n return hex.startsWith('0x') ? hex.slice(2) : hex;\n}\n\n/** Pad hex to 64 chars (32 bytes) with 0x prefix */\nexport function padHex64(hex: string): string {\n return `0x${stripHex(hex).padStart(64, '0')}`;\n}\n\n/**\n * Convert a hex string (with or without 0x prefix) to a Uint8Array.\n * Throws on invalid hex (non-hex characters, odd length).\n */\nexport function hexToBytes(hex: string): Uint8Array {\n return nobleHexToBytes(stripHex(hex));\n}\n\n/** Convert a Uint8Array to a hex string (no 0x prefix). */\nexport function bytesToHex(bytes: Uint8Array): string {\n return nobleBytesToHex(bytes);\n}\n","import { HardwareErrorCode } from '../types/errors';\n\n/**\n * Enrich a hardware error message with actionable recovery hints.\n * Shared across adapters (Ledger, Trezor, etc.).\n */\nexport function enrichErrorMessage(code: HardwareErrorCode, originalMessage: string): string {\n switch (code) {\n case HardwareErrorCode.PinInvalid:\n return `${originalMessage}. Please re-enter your PIN.`;\n case HardwareErrorCode.PinCancelled:\n return `${originalMessage}. PIN entry was cancelled.`;\n case HardwareErrorCode.DeviceBusy:\n return `${originalMessage}. The device is in use by another application. Close other wallet apps and try again.`;\n case HardwareErrorCode.DeviceDisconnected:\n return `${originalMessage}. Please reconnect the device and try again.`;\n case HardwareErrorCode.DeviceLocked:\n return `${originalMessage}. Please unlock your device and try again.`;\n case HardwareErrorCode.DeviceOneDeviceOnly:\n return `${originalMessage}. Disconnect the extra device and try again.`;\n case HardwareErrorCode.UserRejected:\n return `${originalMessage}. The request was rejected on the device.`;\n case HardwareErrorCode.WrongApp:\n return `${originalMessage}. Please open the correct app on your device.`;\n case HardwareErrorCode.AppNotInstalled:\n return `${originalMessage}. The required app is not installed on the device.`;\n case HardwareErrorCode.DeviceOutOfMemory:\n return `${originalMessage}. Not enough free space on the device. Please uninstall some apps and try again.`;\n case HardwareErrorCode.TransportNotAvailable:\n return `${originalMessage}. Ensure the device bridge/transport is available and running.`;\n case HardwareErrorCode.FirmwareTooOld:\n return `${originalMessage}. Please update your device firmware.`;\n case HardwareErrorCode.DeviceNotInitialized:\n return `${originalMessage}. The device may need to be set up first.`;\n case HardwareErrorCode.OperationTimeout:\n return `${originalMessage}. The operation timed out. Please try again.`;\n case HardwareErrorCode.EvmBlindSigningRequired:\n return 'Ledger: Blind signing not enabled in Ethereum app.';\n case HardwareErrorCode.EvmClearSignPluginMissing:\n return 'Ledger: Required plugin not installed (install via Ledger Live).';\n case HardwareErrorCode.EvmDataTooLarge:\n return 'Ledger: Transaction data too large for device memory.';\n case HardwareErrorCode.EvmTxTypeNotSupported:\n return 'Ledger: Transaction type not supported by current Ethereum app.';\n case HardwareErrorCode.AppTooOld:\n return 'Ledger: App out of date (update via Ledger Live).';\n case HardwareErrorCode.SolanaBlindSigningRequired:\n return 'Blind signing disabled in the Solana app.';\n case HardwareErrorCode.TronCustomContractRequired:\n return 'Custom Contracts setting disabled in the Tron app.';\n case HardwareErrorCode.TronDataSigningRequired:\n return 'Transactions Data setting disabled in the Tron app.';\n case HardwareErrorCode.TronSignByHashRequired:\n return 'Sign by Hash setting disabled in the Tron app.';\n case HardwareErrorCode.BtcWalletPolicyHmacMismatch:\n return 'Wallet policy not registered or HMAC mismatch.';\n case HardwareErrorCode.BtcUnexpectedState:\n return 'Signing aborted due to unexpected device state.';\n default:\n return originalMessage;\n }\n}\n","import type { Response } from '../types/response';\n\n/**\n * Generic batch call with progress reporting.\n * If any single call fails, returns the failure immediately.\n */\nexport async function batchCall<TParam, TResult>(\n params: TParam[],\n callFn: (p: TParam) => Promise<Response<TResult>>,\n onProgress?: (progress: { index: number; total: number }) => void\n): Promise<Response<TResult[]>> {\n const results: TResult[] = [];\n for (let i = 0; i < params.length; i++) {\n const result = await callFn(params[i]);\n if (!result.success) {\n return result;\n }\n results.push(result.payload);\n onProgress?.({ index: i, total: params.length });\n }\n return { success: true, payload: results };\n}\n"],"mappings":"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","names":["bytesToHex","HardwareErrorCode","EConnectorInteraction","import_utils","nobleHexToBytes","bytesToHex","nobleBytesToHex"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/types/errors.ts","../src/types/response.ts","../src/types/fingerprint.ts","../src/events/device.ts","../src/events/ui-request.ts","../src/events/sdk.ts","../src/utils/DeviceJobQueue.ts","../src/types/connector.ts","../src/utils/TypedEventEmitter.ts","../src/utils/UiRequestRegistry.ts","../src/utils/semver.ts","../src/utils/hex.ts","../src/utils/errorMessages.ts","../src/utils/batchCall.ts"],"sourcesContent":["export { HardwareErrorCode, ORPHAN_ELIGIBLE_ERROR_CODES, createHwkError } from './types/errors';\nexport type { HwkError, IHwkErrorPayload } from './types/errors';\n\nexport type { Success, Failure, Response } from './types/response';\nexport { success, failure } from './types/response';\n\nexport type {\n VendorType,\n ConnectionType,\n TransportType,\n DeviceInfo,\n DeviceTarget,\n DeviceCapabilities,\n} from './types/device';\n\nexport type {\n EvmGetAddressParams,\n EvmAddress,\n EvmSignTxParams,\n EvmSignedTx,\n EvmSignMsgParams,\n EvmSignTypedDataParams,\n EvmSignTypedDataFull,\n EvmSignTypedDataHash,\n EIP712Domain,\n EvmSignature,\n IEvmMethods,\n} from './types/chain-evm';\n\nexport type {\n BtcGetAddressParams,\n BtcAddress,\n BtcGetPublicKeyParams,\n BtcPublicKey,\n BtcSignTxParams,\n BtcTxInput,\n BtcTxOutput,\n BtcRefTransaction,\n BtcSignedTx,\n BtcSignPsbtParams,\n BtcSignedPsbt,\n BtcSignMsgParams,\n BtcSignature,\n IBtcMethods,\n} from './types/chain-btc';\n\nexport type {\n SolGetAddressParams,\n SolAddress,\n SolSignTxParams,\n SolSignedTx,\n SolSignMsgParams,\n SolSignature,\n ISolMethods,\n} from './types/chain-sol';\n\nexport type {\n TronGetAddressParams,\n TronAddress,\n TronSignTxParams,\n TronSignedTx,\n TronSignMsgParams,\n TronSignature,\n ITronMethods,\n} from './types/chain-tron';\n\nexport type { QrDisplayData, QrResponseData } from './types/qr';\n\nexport type { ChainForFingerprint } from './types/fingerprint';\nexport { CHAIN_FINGERPRINT_PATHS, deriveDeviceFingerprint } from './types/fingerprint';\n\nexport type {\n IHardwareWallet,\n SearchDevicesOptions,\n PassphraseResponse,\n ChainCapability,\n ICommonCallParams,\n AllNetworkAddressParams,\n AllNetworkGetAddressParams,\n AllNetworkAddressResponsePayload,\n AllNetworkAddressResponse,\n DeviceEvent,\n UiRequestEvent,\n SdkEvent,\n HardwareEvent,\n HardwareUiEvent,\n HardwareEventMap,\n DeviceEventListener,\n} from './types/wallet';\n\nexport { DEVICE_EVENT, DEVICE } from './events/device';\nexport { UI_EVENT, UI_REQUEST, UI_RESPONSE } from './events/ui-request';\nexport type {\n DevicePermissionDeniedReason,\n DevicePermissionResponse,\n UiResponseEvent,\n} from './events/ui-request';\nexport { SDK } from './events/sdk';\n\nexport type {\n DeviceDescriptor,\n DeviceConnectEvent,\n DeviceDisconnectEvent,\n DeviceChangeEvent,\n} from './types/transport';\n\nexport { DeviceJobQueue } from './utils/DeviceJobQueue';\nexport type { JobOptions, ActiveJobInfo } from './utils/DeviceJobQueue';\n\nexport type {\n ConnectorDevice,\n ConnectorSession,\n ConnectorEventType,\n ConnectorEventMap,\n ConnectorUiEvent,\n ConnectorCallResult,\n ConnectorSerializedError,\n ConnectorErrorParams,\n IConnector,\n IHardwareBridge,\n} from './types/connector';\nexport {\n createBridgedConnector,\n EConnectorInteraction,\n serializeConnectorError,\n rehydrateConnectorError,\n} from './types/connector';\n\nexport { TypedEventEmitter } from './utils/TypedEventEmitter';\nexport {\n UiRequestRegistry,\n UI_REQUEST_DEFAULT_TIMEOUT_MS,\n UI_REQUEST_PREEMPTED_TAG,\n UI_REQUEST_CANCELLED_TAG,\n UI_REQUEST_TIMEOUT_TAG,\n} from './utils/UiRequestRegistry';\nexport { compareSemver } from './utils/semver';\nexport { ensure0x, stripHex, padHex64, hexToBytes, bytesToHex } from './utils/hex';\nexport { enrichErrorMessage } from './utils/errorMessages';\nexport { batchCall } from './utils/batchCall';\n","/**\n * HWK HardwareErrorCode — independent namespace from the legacy\n * `@onekeyfe/shared` HardwareErrorCode (which occupies 0-902).\n *\n * All HWK codes are 5-digit (>= 10000) so the two tables never collide\n * even if either side grows. Each sub-category gets a 100-slot block.\n *\n * 10000-10099 Generic / cross-cutting primitives\n * 10100-10199 Device state\n * 10200-10299 Firmware\n * 10300-10399 Transport + OS-level permission\n * 10400-10499 PIN / Passphrase\n * 10500-10599 App lifecycle (wrong app, not open, too old)\n * 10600-10999 RESERVED — future adapter-level categories\n *\n * 11000-11099 EVM APDU (reactive mapping)\n * 11100-11199 Solana APDU\n * 11200-11299 Tron APDU\n * 11300-11399 BTC APDU\n * 11400-11999 RESERVED — future chain APDU blocks (100 per chain)\n *\n * 12000-99999 RESERVED — future major categories\n */\nexport enum HardwareErrorCode {\n // --- 10000s Generic ---\n UnknownError = 10000,\n UserRejected = 10001,\n InvalidParams = 10002,\n OperationTimeout = 10003,\n MethodNotSupported = 10004,\n /** User dismissed in-app cancel UI. Distinct from UserRejected (on-device). */\n UserAborted = 10005,\n\n // --- 10100s Device state ---\n DeviceNotFound = 10100,\n DeviceDisconnected = 10101,\n DeviceBusy = 10102,\n DeviceLocked = 10103,\n DeviceNotInitialized = 10104,\n DeviceInBootloader = 10105,\n DeviceMismatch = 10106,\n /** Chain app wedged (e.g. Ledger BTC 0x6901). User must exit app on device. */\n DeviceAppStuck = 10107,\n /** Vendor (Ledger / Trezor) doesn't support the chain at all. */\n ChainNotSupported = 10108,\n /** Current operation supports only one connected device. */\n DeviceOneDeviceOnly = 10109,\n\n // --- 10200s Firmware ---\n FirmwareTooOld = 10200,\n FirmwareUpdateRequired = 10201,\n\n // --- 10300s Transport + permission ---\n TransportError = 10300,\n BridgeNotFound = 10301,\n TransportNotAvailable = 10302,\n /**\n * OS-level permission (Bluetooth / USB / etc.) — denied, blocked,\n * unavailable, or dismissed. Consumers surface a single \"please grant\n * permission\" toast and let the user retry manually.\n */\n DevicePermissionDenied = 10303,\n /**\n * BLE SMP pairing did not complete within the GATT bonding window.\n * GATT connected but the device didn't acknowledge SMP — typically\n * because the user didn't confirm the passkey on the device, or the\n * device went out of range mid-pairing. Distinct from OperationTimeout\n * (generic) and from DeviceLocked (Secure Element actually locked).\n */\n BlePairingTimeout = 10304,\n /** Remote network failure reaching a vendor's servers (HTTP/WS). Distinct from TransportError (local USB/BLE link). */\n NetworkError = 10305,\n\n // --- 10400s PIN / Passphrase ---\n PinInvalid = 10400,\n PinCancelled = 10401,\n PassphraseRejected = 10402,\n\n // --- 10500s App lifecycle ---\n /** Chain app NOT INSTALLED on device. User must install via Ledger Live. */\n AppNotInstalled = 10500,\n WrongApp = 10501,\n /** 0x911c Command code not supported — app predates current SDK. */\n AppTooOld = 10502,\n /** Not enough free storage for install/update; user must uninstall apps first. */\n DeviceOutOfMemory = 10503,\n\n // --- 11000s EVM (Ledger Ethereum App) APDU-specific ---\n /** 0x6a80 Invalid data — observed on blindSignTransactionFallback when the\n * user has not enabled Blind signing on the device. */\n EvmBlindSigningRequired = 11000,\n /** 0x6984 Plugin not installed */\n EvmClearSignPluginMissing = 11001,\n /** 0x6a84 Insufficient memory (typical on Nano S with large calldata) */\n EvmDataTooLarge = 11002,\n /** 0x6501 TransactionType not supported (app too old for EIP-1559 / blob / 7702) */\n EvmTxTypeNotSupported = 11003,\n\n // --- 11100s Solana ---\n /** 0x6808 Blind signing disabled for this instruction. */\n SolanaBlindSigningRequired = 11100,\n\n // --- 11200s Tron ---\n /** 0x6a8d Custom Contracts setting disabled (blocks TRC-20 etc.). */\n TronCustomContractRequired = 11200,\n /** 0x6a8b Transactions Data setting disabled. */\n TronDataSigningRequired = 11201,\n /** 0x6a8c Sign by Hash setting disabled (hash-signing fallback). */\n TronSignByHashRequired = 11202,\n\n // --- 11300s BTC ---\n /** 0xb008 Wallet policy HMAC mismatch or not registered. */\n BtcWalletPolicyHmacMismatch = 11300,\n /** 0xb007 Aborted due to unexpected state (malformed PSBT / missing UTXO). */\n BtcUnexpectedState = 11301,\n}\n\n/**\n * Device-level failures the SDK cannot self-recover from — affect the entire\n * batch (vs per-chain failures like AppNotInstalled / WrongApp which soft-\n * skip in onboarding). Combined with `accounts.length === 0`, signals\n * genuine orphan. Also reused as the batch-abort whitelist for HWK.\n * Single source of truth.\n *\n * UserRejected (device-side reject) is included: pressing reject is an\n * explicit \"I don't consent\" — continuing the batch to ask again on the\n * next chain is harassment, not helpful.\n */\nexport const ORPHAN_ELIGIBLE_ERROR_CODES: number[] = [\n HardwareErrorCode.UserAborted,\n HardwareErrorCode.UserRejected,\n HardwareErrorCode.DeviceNotFound,\n HardwareErrorCode.DeviceDisconnected,\n HardwareErrorCode.DeviceMismatch,\n HardwareErrorCode.DeviceAppStuck,\n HardwareErrorCode.DeviceOneDeviceOnly,\n HardwareErrorCode.TransportError,\n HardwareErrorCode.DevicePermissionDenied,\n HardwareErrorCode.BlePairingTimeout,\n];\n\n// ---------------------------------------------------------------------------\n// Standard throwable for HWK adapters\n// ---------------------------------------------------------------------------\n\nexport interface IHwkErrorPayload {\n code: HardwareErrorCode;\n message: string;\n appName?: string;\n _tag?: string;\n params?: Record<string, unknown>;\n}\n\nexport type HwkError = Error & {\n code: HardwareErrorCode;\n appName?: string;\n _tag?: string;\n params?: Record<string, unknown>;\n};\n\n/**\n * Canonical throwable for HWK adapters. Plain Error + canonical extra fields,\n * shape-compatible with `rehydrateConnectorError` so locally-thrown and\n * cross-boundary errors are indistinguishable to downstream classifiers\n * (`err.code` / `err._tag` / `err.appName`). Do NOT mutate caught errors\n * with `Object.assign` — construct a fresh one via this factory.\n */\nexport function createHwkError(payload: IHwkErrorPayload): HwkError {\n return Object.assign(new Error(payload.message), {\n code: payload.code,\n ...(payload._tag !== undefined && { _tag: payload._tag }),\n ...(payload.appName !== undefined && { appName: payload.appName }),\n ...(payload.params !== undefined && { params: payload.params }),\n });\n}\n","import type { HardwareErrorCode } from './errors';\n\nexport interface Success<T> {\n success: true;\n payload: T;\n}\n\nexport interface Failure {\n success: false;\n payload: {\n error: string;\n code: HardwareErrorCode;\n params?: Record<string, unknown>;\n };\n}\n\nexport type Response<T> = Success<T> | Failure;\n\nexport function success<T>(payload: T): Success<T> {\n return { success: true, payload };\n}\n\nexport function failure(\n code: HardwareErrorCode,\n error: string,\n params?: Record<string, unknown>\n): Failure {\n return {\n success: false,\n payload: { error, code, ...(params ? { params } : {}) },\n };\n}\n","/**\n * Chain fingerprint utilities for device identity verification.\n *\n * Ledger devices have ephemeral IDs that change every session.\n * To verify that the same seed/device is connected, we derive an address\n * at a fixed path (account 0, index 0) and hash it into a stable \"chain fingerprint\".\n */\nimport { sha256 } from '@noble/hashes/sha256';\nimport { bytesToHex, utf8ToBytes } from '@noble/hashes/utils';\n\n/**\n * Fixed derivation paths used to generate chain fingerprints.\n * Uses standard index 0 — Ledger firmware shows device confirmation for\n * non-standard paths (e.g., index=100), which would interrupt wallet creation.\n * The address is hashed into a 16-char fingerprint, not exposed directly.\n * - EVM: cointype 60 (Ledger ETH App only supports 60)\n * - BTC: cointype 1 (testnet)\n * - SOL: cointype 501, standard 3-level hardened\n */\nexport const CHAIN_FINGERPRINT_PATHS: Record<ChainForFingerprint, string> = {\n evm: \"m/44'/60'/0'/0/0\",\n // BTC: account-level path (3 levels), mainnet cointype 0.\n // Cointype 1 (testnet) is rejected by some Ledger BTC App configurations.\n btc: \"m/44'/0'/0'\",\n sol: \"m/44'/501'/0'\",\n tron: \"m/44'/195'/0'/0/0\",\n};\n\nexport type ChainForFingerprint = 'evm' | 'btc' | 'sol' | 'tron';\n\n/**\n * 16-char SHA-256 fingerprint for device-identity verification.\n * Callers must canonicalize input (e.g. EVM address → lowercase) —\n * encoding variations otherwise cause false DeviceMismatch.\n */\nexport function deriveDeviceFingerprint(value: string): string {\n return bytesToHex(sha256(utf8ToBytes(value))).slice(0, 16);\n}\n","export const DEVICE_EVENT = 'DEVICE_EVENT';\n\n/** Events originating from the hardware device. */\nexport const DEVICE = {\n CONNECT: 'device-connect',\n DISCONNECT: 'device-disconnect',\n CHANGED: 'device-changed',\n} as const;\n","import type { QrResponseData } from '../types/qr';\n\nexport const UI_EVENT = 'UI_EVENT';\n\nexport const UI_REQUEST = {\n REQUEST_PIN: 'ui-request-pin',\n REQUEST_PASSPHRASE: 'ui-request-passphrase',\n REQUEST_PASSPHRASE_ON_DEVICE: 'ui-request-passphrase-on-device',\n REQUEST_BUTTON: 'ui-request-button',\n REQUEST_QR_DISPLAY: 'ui-request-qr-display',\n REQUEST_QR_SCAN: 'ui-request-qr-scan',\n REQUEST_DEVICE_PERMISSION: 'ui-request-device-permission',\n REQUEST_SELECT_DEVICE: 'ui-request-select-device',\n REQUEST_DEVICE_CONNECT: 'ui-request-device-connect',\n // Ledger BTC App: account index >= 100 requires display=true. Adapter asks\n // the user once per session before promoting the call.\n REQUEST_BTC_HIGH_INDEX_CONFIRM: 'ui-request-btc-high-index-confirm',\n // Required app is not installed; with autoInstallApp on, ask the user\n // whether to install it before retrying the operation.\n REQUEST_INSTALL_APP: 'ui-request-install-app',\n CLOSE_UI_WINDOW: 'ui-close',\n DEVICE_PROGRESS: 'ui-device_progress',\n FIRMWARE_PROGRESS: 'ui-firmware-progress',\n FIRMWARE_TIP: 'ui-firmware-tip',\n} as const;\n\nexport const UI_RESPONSE = {\n RECEIVE_PIN: 'receive-pin',\n RECEIVE_PASSPHRASE: 'receive-passphrase',\n RECEIVE_PASSPHRASE_ON_DEVICE: 'receive-passphrase-on-device',\n RECEIVE_QR_RESPONSE: 'receive-qr-response',\n RECEIVE_SELECT_DEVICE: 'receive-select-device',\n RECEIVE_DEVICE_CONNECT: 'receive-device-connect',\n RECEIVE_DEVICE_PERMISSION: 'receive-device-permission',\n RECEIVE_BTC_HIGH_INDEX_CONFIRM: 'receive-btc-high-index-confirm',\n RECEIVE_INSTALL_APP: 'receive-install-app',\n CANCEL: 'cancel',\n} as const;\n\nexport type DevicePermissionDeniedReason =\n | 'bluetoothTurnedOff'\n | 'permissionDenied'\n | (string & Record<never, never>);\n\nexport type DevicePermissionResponse = {\n granted: boolean;\n reason?: DevicePermissionDeniedReason;\n message?: string;\n};\n\nexport type UiResponseEvent =\n | {\n type: typeof UI_RESPONSE.RECEIVE_PIN;\n payload: string;\n }\n | {\n type: typeof UI_RESPONSE.RECEIVE_PASSPHRASE;\n payload: {\n value: string;\n passphraseOnDevice?: boolean;\n save?: boolean;\n };\n }\n | {\n type: typeof UI_RESPONSE.RECEIVE_PASSPHRASE_ON_DEVICE;\n payload?: undefined;\n }\n | {\n type: typeof UI_RESPONSE.RECEIVE_QR_RESPONSE;\n payload: QrResponseData;\n }\n | {\n // sdkConnectId echoes one of the DeviceInfo.connectId values emitted in\n // the REQUEST_SELECT_DEVICE event's `devices` list. Scope is the current\n // search session; may be ephemeral (e.g. Ledger USB DMK UUID).\n type: typeof UI_RESPONSE.RECEIVE_SELECT_DEVICE;\n payload: { sdkConnectId: string };\n }\n | {\n type: typeof UI_RESPONSE.RECEIVE_DEVICE_CONNECT;\n payload: { confirmed: boolean };\n }\n | {\n type: typeof UI_RESPONSE.RECEIVE_DEVICE_PERMISSION;\n payload: DevicePermissionResponse;\n }\n | {\n type: typeof UI_RESPONSE.RECEIVE_BTC_HIGH_INDEX_CONFIRM;\n payload: { confirmed: boolean };\n }\n | {\n type: typeof UI_RESPONSE.RECEIVE_INSTALL_APP;\n payload: { confirmed: boolean };\n }\n | {\n type: typeof UI_RESPONSE.CANCEL;\n payload?: undefined;\n };\n","/** Events generated by SDK internal detection (not from hardware directly). */\nexport const SDK = {\n DEVICE_STUCK: 'device-stuck',\n DEVICE_UNRESPONSIVE: 'device-unresponsive',\n DEVICE_RECOVERED: 'device-recovered',\n DEVICE_INTERACTION: 'device-interaction',\n} as const;\n","/**\n * Pure FIFO job queue. Every enqueue chains onto the tail; jobs run one at\n * a time across all devices. The queue is intentionally passive — it does\n * NOT decide whether to interrupt or ask the user. Those are application-\n * layer concerns owned by the caller (e.g. a UI button handler that wants\n * to ask \"device is busy, interrupt current?\" before submitting). The\n * queue exposes inspection (`getActiveJob`) and explicit cancellation\n * (`cancelActive` / `cancelAll`) so callers can implement those policies\n * synchronously, without racing against in-flight enqueues.\n */\n\nexport interface JobOptions {\n label?: string;\n rejectIfBusy?: boolean;\n busyError?: Error;\n}\n\nexport interface ActiveJobInfo {\n deviceId: string;\n label?: string;\n startedAt: number;\n}\n\ninterface ActiveJob {\n deviceId: string;\n label?: string;\n abortController: AbortController;\n startedAt: number;\n}\n\nexport class DeviceJobQueue {\n private _tail: Promise<unknown> = Promise.resolve();\n\n private _active: ActiveJob | null = null;\n\n private readonly _jobs = new Map<object, { deviceId: string }>();\n\n /** Incremented on clear() so queued-but-not-yet-running jobs detect invalidation. */\n private _generation = 0;\n\n private readonly _generationCancelReasons = new Map<number, Error>();\n\n /**\n * Enqueue a job. Runs after every previously-enqueued job has settled.\n * `deviceId` is a label only — used by inspection / cancellation routing.\n */\n async enqueue<T>(\n deviceId: string,\n job: (signal: AbortSignal) => Promise<T>,\n options: JobOptions = {}\n ): Promise<T> {\n if (options.rejectIfBusy && this._jobs.size > 0) {\n throw options.busyError ?? new Error('Device is busy');\n }\n\n const ac = new AbortController();\n const gen = this._generation;\n const prev = this._tail;\n const jobToken = {};\n const activeJob: ActiveJob = {\n deviceId,\n label: options.label,\n abortController: ac,\n startedAt: Date.now(),\n };\n this._jobs.set(jobToken, { deviceId });\n\n const next = prev\n .catch(() => {})\n .then(async () => {\n if (this._generation !== gen) {\n throw (\n this._generationCancelReasons.get(gen) ?? new Error('Job cancelled: queue was cleared')\n );\n }\n this._active = activeJob;\n try {\n return await job(ac.signal);\n } finally {\n // Identity guard: a previous job's deferred finally must not\n // null out a successor's `_active`.\n if (this._active === activeJob) {\n this._active = null;\n }\n }\n })\n .finally(() => {\n this._jobs.delete(jobToken);\n });\n\n this._tail = next.catch(() => {});\n return next;\n }\n\n /** Cancel the active job. If `deviceId` is given, only cancels when it matches. */\n cancelActive(deviceId?: string): boolean {\n if (!this._active) return false;\n if (deviceId && this._active.deviceId !== deviceId) return false;\n this._active.abortController.abort(new Error('Manually cancelled'));\n return true;\n }\n\n /** Force cancel the active job. `reason` becomes signal.reason. */\n forceCancelActive(deviceId?: string, reason?: Error): boolean {\n if (!this._active) return false;\n if (deviceId && this._active.deviceId !== deviceId) return false;\n this._active.abortController.abort(reason ?? new Error('Force cancelled for recovery'));\n return true;\n }\n\n /** Cancel the active job (alias for callers that previously needed multi-device cancel). */\n cancelAllActive(reason?: Error): void {\n if (!this._active) return;\n this._active.abortController.abort(reason ?? new Error('Cancelled by cancelAllActive'));\n }\n\n /** Cancel the active job and invalidate queued jobs that have not started. */\n cancelActiveAndPending(deviceId?: string, reason?: Error): boolean {\n if (deviceId && this._active && this._active.deviceId !== deviceId) {\n return false;\n }\n this.clear(reason ?? new Error('Cancelled by cancelActiveAndPending'));\n return true;\n }\n\n /** Get info about the currently active job, or null if idle. */\n getActiveJob(deviceId?: string): ActiveJobInfo | null {\n if (!this._active) return null;\n if (deviceId && this._active.deviceId !== deviceId) return null;\n return {\n deviceId: this._active.deviceId,\n label: this._active.label,\n startedAt: this._active.startedAt,\n };\n }\n\n /** True if any job is currently running. */\n isBusy(): boolean {\n return this._jobs.size > 0;\n }\n\n clear(reason?: Error): void {\n const cancelledGeneration = this._generation;\n this._generation++;\n const cancelReason = reason ?? new Error('Job cancelled: queue was cleared');\n this._generationCancelReasons.set(cancelledGeneration, cancelReason);\n for (const generation of this._generationCancelReasons.keys()) {\n if (generation < this._generation - 10) {\n this._generationCancelReasons.delete(generation);\n }\n }\n if (this._active) {\n this._active.abortController.abort(cancelReason);\n }\n }\n}\n","import type { ConnectionType, DeviceCapabilities, DeviceInfo, VendorType } from './device';\nimport type { UiResponseEvent } from '../events/ui-request';\n\n// =====================================================================\n// Connector types — transport-level abstraction for device communication\n// =====================================================================\n\n/**\n * Minimal device info returned during discovery (searchDevices).\n * At scan time, full DeviceInfo fields like firmwareVersion are not yet available.\n */\nexport interface ConnectorDevice {\n connectId: string;\n deviceId: string;\n name: string;\n /** Machine model id (e.g. \"nanoX\"). */\n model?: string;\n /** Human-readable model name (e.g. \"Ledger Nano X\"). */\n modelName?: string;\n /** BLE signal strength (BLE only). */\n rssi?: number | null;\n /** BLE connectable flag (BLE only). */\n isConnectable?: boolean | null;\n /** USB serial number (USB only). */\n serialNumber?: string;\n\n /** Device capabilities — available from scan time */\n capabilities?: DeviceCapabilities;\n}\n\nexport interface ConnectorSession {\n sessionId: string;\n deviceInfo: DeviceInfo;\n}\n\n// =====================================================================\n// Connector call result — device errors travel as DATA, not exceptions\n//\n// `IConnector.call` never throws for device-level failures. It resolves a\n// discriminated result so the failure crosses any process boundary\n// (IHardwareBridge / extension offscreen↔SW) as plain `data`. This mirrors\n// the OneKey HD-SDK `IDeviceResponseResult` contract.\n//\n// WHY: when a thrown Error crosses the extension JsBridge it is run through\n// `toPlainError`, a fixed field whitelist that drops custom own-properties\n// (e.g. `appName`). Returning the failure as data keeps every field intact.\n//\n// Contract for `ConnectorSerializedError`: only `message` / `code` /\n// `errorCode` live at the top level; ALL other domain fields (`appName`,\n// `_tag`, `statusCode`, …) are nested under `params`.\n// =====================================================================\n\n/**\n * Vendor-agnostic bag of extra error fields. Known keys are documented for\n * discoverability; the index signature keeps it open so any connector can\n * carry vendor-specific data without losing it across the bridge.\n */\nexport interface ConnectorErrorParams {\n /** Vendor SDK error tag (e.g. Ledger DMK `_tag`). */\n _tag?: string;\n /** App involved, e.g. the Ledger app being opened/installed. */\n appName?: string;\n /** Transport / APDU status code (string or number depending on vendor). */\n statusCode?: unknown;\n /**\n * Shallow snapshot of a nested cause. A raw Error does not survive JSON\n * serialization (its `message`/`stack` are non-enumerable), so recovery\n * predicates that recurse into a cause get this plain-object copy instead.\n */\n originalError?: {\n message?: string;\n code?: number;\n errorCode?: string;\n statusCode?: unknown;\n _tag?: string;\n };\n [key: string]: unknown;\n}\n\nexport interface ConnectorSerializedError {\n message: string;\n code?: number;\n errorCode?: string;\n params?: ConnectorErrorParams;\n}\n\nexport type ConnectorCallResult =\n | { success: true; payload: unknown }\n | { success: false; error: ConnectorSerializedError };\n\nexport type ConnectorEventType = 'device-connect' | 'device-disconnect' | 'ui-request' | 'ui-event';\n\n/**\n * Interaction event types emitted via 'ui-event'.\n * These map to user-facing prompts (confirm on device, open app, etc.).\n */\nexport enum EConnectorInteraction {\n /** Adapter is actively searching for the device (no session yet) */\n Searching = 'searching',\n /** Device requires user to open a specific app */\n ConfirmOpenApp = 'confirm-open-app',\n /** Device requires user to unlock */\n UnlockDevice = 'unlock-device',\n /** Device needs user to confirm on device (sign, verify, etc.) */\n ConfirmOnDevice = 'confirm-on-device',\n /** Previous interaction completed — clear UI prompt */\n InteractionComplete = 'interaction-complete',\n /**\n * OS-level Ledger app install progress. `progress` is a 0..1 fraction\n * reported by DMK's InstallOrUpdateAppsDeviceAction. Emitted from inside\n * the connector so the progress callback ref never has to cross the\n * IHardwareBridge boundary.\n */\n AppInstallProgress = 'app-install-progress',\n}\n\n// Discriminated union: most variants only carry `sessionId`, but\n// AppInstallProgress also carries `appName` + `progress`. Searching has no\n// session yet so it carries an empty `sessionId`.\nexport type ConnectorUiEvent =\n | { type: EConnectorInteraction.Searching; payload: { sessionId: string } }\n | { type: EConnectorInteraction.ConfirmOpenApp; payload: { sessionId: string } }\n | { type: EConnectorInteraction.UnlockDevice; payload: { sessionId: string } }\n | { type: EConnectorInteraction.ConfirmOnDevice; payload: { sessionId: string } }\n | { type: EConnectorInteraction.InteractionComplete; payload: { sessionId: string } }\n | {\n type: EConnectorInteraction.AppInstallProgress;\n payload: { sessionId: string; appName: string; progress: number };\n };\n\nexport interface ConnectorEventMap {\n 'device-connect': { device: ConnectorDevice };\n 'device-disconnect': { connectId: string };\n 'ui-request': { type: string; payload?: unknown };\n 'ui-event': ConnectorUiEvent;\n}\n\nexport interface IConnector {\n /** Physical connection type this connector uses. Fixed at construction. */\n readonly connectionType: ConnectionType;\n\n searchDevices(): Promise<ConnectorDevice[]>;\n connect(deviceId?: string): Promise<ConnectorSession>;\n disconnect(sessionId: string): Promise<void>;\n // `call` resolves a discriminated result; device-level failures are returned\n // as data, never thrown (see ConnectorCallResult). Only `call` uses this\n // contract because it is the one method that carries rich, vendor-specific\n // domain errors across the IHardwareBridge boundary, where a thrown Error\n // would be stripped by the host bridge's error whitelist. The other methods\n // surface plain operational failures and still reject normally.\n call(sessionId: string, method: string, params: unknown): Promise<ConnectorCallResult>;\n cancel(sessionId: string): Promise<void>;\n\n /** Send a UI response (e.g. PIN, passphrase) to the device. */\n uiResponse(response: UiResponseEvent): void;\n\n on<K extends ConnectorEventType>(event: K, handler: (data: ConnectorEventMap[K]) => void): void;\n off<K extends ConnectorEventType>(event: K, handler: (data: ConnectorEventMap[K]) => void): void;\n\n reset(): void;\n}\n\n// =====================================================================\n// Hardware bridge — generic forwarding interface for cross-boundary IConnector\n//\n// The same shape works across any process / context boundary that needs to\n// expose a multi-vendor backend behind a single-vendor IConnector facade:\n// - Electron (renderer ↔ preload/main via contextBridge)\n// - Browser Extension (popup/content ↔ background/offscreen via chrome.runtime)\n// - React Native (JS ↔ native module via NativeModules)\n// - Web Worker / iframe (postMessage)\n//\n// Each method takes a `vendor` discriminator so a single bridge implementation\n// can multiplex across vendors (ledger, trezor, ...).\n// =====================================================================\n\nexport interface IHardwareBridge {\n searchDevices(params: { vendor: VendorType }): Promise<ConnectorDevice[]>;\n connect(params: { vendor: VendorType; deviceId?: string }): Promise<ConnectorSession>;\n disconnect(params: { vendor: VendorType; sessionId: string }): Promise<void>;\n call(params: {\n vendor: VendorType;\n sessionId: string;\n method: string;\n callParams: unknown;\n }): Promise<ConnectorCallResult>;\n cancel(params: { vendor: VendorType; sessionId: string }): Promise<void>;\n uiResponse(params: { vendor: VendorType; response: UiResponseEvent }): void;\n reset(params: { vendor: VendorType }): void;\n\n /** Register an event handler for connector events forwarded across the bridge. */\n onEvent(\n params: { vendor: VendorType },\n handler: (event: { type: ConnectorEventType; data: unknown }) => void\n ): void;\n\n /** Unregister a previously registered event handler. */\n offEvent(\n params: { vendor: VendorType },\n handler: (event: { type: ConnectorEventType; data: unknown }) => void\n ): void;\n}\n\n/**\n * Adapt an IHardwareBridge (multi-vendor backend) into a single-vendor IConnector.\n * Every IConnector method becomes a transparent forward to bridge.<method>({ vendor, ... }).\n * Events are forwarded via bridge.onEvent / offEvent.\n *\n * Use this anywhere the actual hardware lives behind a process / context boundary\n * (Electron main, extension background, native module, worker, iframe).\n */\nexport function createBridgedConnector(\n vendor: VendorType,\n connectionType: ConnectionType,\n bridge: IHardwareBridge\n): IConnector {\n // Keyed by (event, handler). A flat handler-only map would collide when the\n // same function is registered for multiple events — second .on() would\n // overwrite the first bridge handler reference, leaking it permanently.\n type UserHandler = (data: ConnectorEventMap[ConnectorEventType]) => void;\n type BridgeHandler = (event: { type: ConnectorEventType; data: unknown }) => void;\n const handlerMap = new Map<ConnectorEventType, Map<UserHandler, BridgeHandler>>();\n\n return {\n connectionType,\n searchDevices: () => bridge.searchDevices({ vendor }),\n connect: deviceId => bridge.connect({ vendor, deviceId }),\n disconnect: sessionId => bridge.disconnect({ vendor, sessionId }),\n call: (sessionId, method, callParams) => bridge.call({ vendor, sessionId, method, callParams }),\n cancel: sessionId => bridge.cancel({ vendor, sessionId }),\n uiResponse: response => bridge.uiResponse({ vendor, response }),\n on: (event, handler) => {\n const bridgeHandler: BridgeHandler = e => {\n if (e.type === event) {\n handler(e.data as ConnectorEventMap[typeof event]);\n }\n };\n let inner = handlerMap.get(event);\n if (!inner) {\n inner = new Map();\n handlerMap.set(event, inner);\n }\n inner.set(handler as UserHandler, bridgeHandler);\n bridge.onEvent({ vendor }, bridgeHandler);\n },\n off: (event, handler) => {\n const inner = handlerMap.get(event);\n const bridgeHandler = inner?.get(handler as UserHandler);\n if (!bridgeHandler || !inner) return;\n bridge.offEvent({ vendor }, bridgeHandler);\n inner.delete(handler as UserHandler);\n if (inner.size === 0) handlerMap.delete(event);\n },\n reset: () => bridge.reset({ vendor }),\n };\n}\n\n// =====================================================================\n// ConnectorCallResult error (de)serialization — the canonical, vendor-agnostic\n// helpers every IConnector implementation / adapter should use, so the\n// \"errors as data\" contract is identical across vendors.\n// =====================================================================\n\nconst SERIALIZED_ERROR_TOP_LEVEL_KEYS = new Set([\n 'message',\n 'code',\n 'errorCode',\n 'stack',\n 'params',\n]);\n\n/**\n * Flatten a thrown error into the cross-boundary-safe `ConnectorSerializedError`\n * shape. `message`/`code`/`errorCode` are lifted to the top level; every other\n * own-enumerable field is copied into `params` so NO domain data is lost when\n * the result crosses a host bridge (which may run thrown errors through a\n * field whitelist). A nested `originalError` is shallow-snapshotted because a\n * raw Error does not survive JSON serialization.\n */\nexport function serializeConnectorError(err: unknown): ConnectorSerializedError {\n if (!err || typeof err !== 'object') {\n return { message: typeof err === 'string' ? err : 'Unknown error' };\n }\n const e = err as Record<string, unknown>;\n const message = typeof e.message === 'string' ? e.message : 'Unknown error';\n const code = typeof e.code === 'number' ? e.code : undefined;\n const errorCode = e.errorCode != null ? String(e.errorCode) : undefined;\n\n const params: ConnectorErrorParams = {};\n // Flatten an existing `params` bag, then copy every other own field (so\n // vendor-specific keys like `_tag` / `statusCode` / `appName` / step context\n // are preserved without being named here).\n if (e.params && typeof e.params === 'object') {\n Object.assign(params, e.params as Record<string, unknown>);\n }\n for (const key of Object.keys(e)) {\n if (!SERIALIZED_ERROR_TOP_LEVEL_KEYS.has(key)) {\n params[key] = e[key];\n }\n }\n const orig = e.originalError;\n if (orig && typeof orig === 'object') {\n const o = orig as Record<string, unknown>;\n params.originalError = {\n message: typeof o.message === 'string' ? o.message : undefined,\n code: typeof o.code === 'number' ? o.code : undefined,\n errorCode: o.errorCode != null ? String(o.errorCode) : undefined,\n statusCode: o.statusCode,\n _tag: typeof o._tag === 'string' ? o._tag : undefined,\n };\n }\n\n // The result crosses host bridges via JSON.stringify. Drop any single field\n // that isn't JSON-safe (circular ref / non-serializable) so a pathological\n // error degrades to \"one field missing\" instead of crashing the transport.\n for (const key of Object.keys(params)) {\n try {\n JSON.stringify(params[key]);\n } catch {\n delete params[key];\n }\n }\n\n return {\n message,\n ...(code !== undefined ? { code } : {}),\n ...(errorCode !== undefined ? { errorCode } : {}),\n ...(Object.keys(params).length ? { params } : {}),\n };\n}\n\n/**\n * Inverse of `serializeConnectorError`: rebuild a flat Error instance, lifting\n * `params.*` back to own-properties so existing throw-based classifiers/recovery\n * logic (which read `err._tag` / `err.code` / `err.appName` / …) keep working\n * unchanged. The Result shape stays confined to the connector boundary.\n */\nexport function rehydrateConnectorError(error: ConnectorSerializedError): Error {\n const { message, code, errorCode, params } = error;\n return Object.assign(new Error(message), {\n ...(code !== undefined ? { code } : {}),\n ...(errorCode !== undefined ? { errorCode } : {}),\n ...(params ?? {}),\n });\n}\n","/**\n * Minimal typed event emitter using Map<string, Set<listener>>.\n * Each adapter uses this for device events (connect, disconnect, pin, etc.).\n *\n * TMap is a record mapping event name strings to their payload types.\n * Example:\n * type MyEvents = { 'connect': { id: string }; 'disconnect': { id: string } };\n * const emitter = new TypedEventEmitter<MyEvents>();\n * emitter.on('connect', (data) => { data.id }); // data is { id: string }\n *\n * For backward compatibility, TMap defaults to Record<string, any> so that\n * existing code using `new TypedEventEmitter<SomeUnionType>()` still compiles.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport class TypedEventEmitter<TMap extends Record<string, any> = Record<string, any>> {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private readonly _listeners = new Map<string, Set<(event: any) => void>>();\n\n on<K extends keyof TMap & string>(event: K, listener: (event: TMap[K]) => void): void;\n\n on(event: string, listener: (event: any) => void): void;\n\n on(event: string, listener: (event: any) => void): void {\n let set = this._listeners.get(event);\n if (!set) {\n set = new Set();\n this._listeners.set(event, set);\n }\n set.add(listener);\n }\n\n off<K extends keyof TMap & string>(event: K, listener: (event: TMap[K]) => void): void;\n\n off(event: string, listener: (event: any) => void): void;\n\n off(event: string, listener: (event: any) => void): void {\n const set = this._listeners.get(event);\n if (set) {\n set.delete(listener);\n if (set.size === 0) this._listeners.delete(event);\n }\n }\n\n emit<K extends keyof TMap & string>(event: K, data: TMap[K]): void;\n\n emit(event: string, data: unknown): void;\n\n emit(event: string, data: unknown): void {\n const set = this._listeners.get(event);\n if (set) {\n for (const listener of set) listener(data);\n }\n }\n\n removeAllListeners(): void {\n this._listeners.clear();\n }\n}\n","import { UI_REQUEST, UI_RESPONSE } from '../events/ui-request';\n\n/** 10 min — every UI request is human-in-the-loop; bias toward \"wait long\". */\nexport const UI_REQUEST_DEFAULT_TIMEOUT_MS = 600_000;\n\nconst RESPONSE_TO_REQUEST: Record<string, string> = {\n [UI_RESPONSE.RECEIVE_PIN]: UI_REQUEST.REQUEST_PIN,\n [UI_RESPONSE.RECEIVE_PASSPHRASE]: UI_REQUEST.REQUEST_PASSPHRASE,\n [UI_RESPONSE.RECEIVE_PASSPHRASE_ON_DEVICE]: UI_REQUEST.REQUEST_PASSPHRASE_ON_DEVICE,\n [UI_RESPONSE.RECEIVE_SELECT_DEVICE]: UI_REQUEST.REQUEST_SELECT_DEVICE,\n [UI_RESPONSE.RECEIVE_DEVICE_CONNECT]: UI_REQUEST.REQUEST_DEVICE_CONNECT,\n [UI_RESPONSE.RECEIVE_DEVICE_PERMISSION]: UI_REQUEST.REQUEST_DEVICE_PERMISSION,\n [UI_RESPONSE.RECEIVE_BTC_HIGH_INDEX_CONFIRM]: UI_REQUEST.REQUEST_BTC_HIGH_INDEX_CONFIRM,\n [UI_RESPONSE.RECEIVE_INSTALL_APP]: UI_REQUEST.REQUEST_INSTALL_APP,\n // RECEIVE_QR_RESPONSE maps to QR_DISPLAY or QR_SCAN — resolved dynamically below.\n};\n\nexport const UI_REQUEST_PREEMPTED_TAG = 'UiRequestPreempted';\nexport const UI_REQUEST_CANCELLED_TAG = 'UiRequestCancelled';\nexport const UI_REQUEST_TIMEOUT_TAG = 'UiRequestTimeout';\n\ntype PendingEntry = {\n resolve: (payload: unknown) => void;\n reject: (error: Error) => void;\n timer: ReturnType<typeof setTimeout>;\n};\n\n/**\n * Per-type single-slot registry for adapter-level UI requests. A new `wait`\n * of the same type supersedes (rejects) the prior pending entry. With the\n * job queue running globally serially, cross-type collisions don't occur in\n * normal flow — same-type preemption is a defensive measure for callers\n * that fire the same request twice without waiting on the first.\n *\n * Unknown response types are dropped silently so the public `uiResponse`\n * entry never throws.\n */\nexport class UiRequestRegistry {\n private pending = new Map<string, PendingEntry>();\n\n wait<T = unknown>(requestType: string, options?: { timeoutMs?: number }): Promise<T> {\n const existing = this.pending.get(requestType);\n if (existing) {\n clearTimeout(existing.timer);\n this.pending.delete(requestType);\n existing.reject(\n Object.assign(new Error(`UI request '${requestType}' was superseded by a new request`), {\n _tag: UI_REQUEST_PREEMPTED_TAG,\n })\n );\n }\n\n const timeoutMs = options?.timeoutMs ?? UI_REQUEST_DEFAULT_TIMEOUT_MS;\n\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => {\n if (this.pending.get(requestType)?.timer === timer) {\n this.pending.delete(requestType);\n reject(\n Object.assign(new Error(`UI request '${requestType}' timed out after ${timeoutMs}ms`), {\n _tag: UI_REQUEST_TIMEOUT_TAG,\n })\n );\n }\n }, timeoutMs);\n\n this.pending.set(requestType, {\n resolve: resolve as (payload: unknown) => void,\n reject,\n timer,\n });\n });\n }\n\n resolve(responseType: string, payload: unknown): void {\n let requestType = RESPONSE_TO_REQUEST[responseType];\n if (responseType === UI_RESPONSE.RECEIVE_QR_RESPONSE) {\n if (this.pending.has(UI_REQUEST.REQUEST_QR_DISPLAY)) {\n requestType = UI_REQUEST.REQUEST_QR_DISPLAY;\n } else if (this.pending.has(UI_REQUEST.REQUEST_QR_SCAN)) {\n requestType = UI_REQUEST.REQUEST_QR_SCAN;\n }\n }\n if (!requestType) return;\n\n const entry = this.pending.get(requestType);\n if (!entry) return;\n\n clearTimeout(entry.timer);\n this.pending.delete(requestType);\n entry.resolve(payload);\n }\n\n cancel(requestType?: string): void {\n if (requestType) {\n const entry = this.pending.get(requestType);\n if (!entry) return;\n clearTimeout(entry.timer);\n this.pending.delete(requestType);\n entry.reject(\n Object.assign(new Error(`UI request '${requestType}' was cancelled`), {\n _tag: UI_REQUEST_CANCELLED_TAG,\n })\n );\n return;\n }\n\n for (const [type, entry] of this.pending) {\n clearTimeout(entry.timer);\n entry.reject(\n Object.assign(new Error(`UI request '${type}' was cancelled`), {\n _tag: UI_REQUEST_CANCELLED_TAG,\n })\n );\n }\n this.pending.clear();\n }\n\n reset(): void {\n this.cancel();\n }\n\n hasPending(requestType?: string): boolean {\n if (requestType) return this.pending.has(requestType);\n return this.pending.size > 0;\n }\n}\n","/**\n * Compare two semver strings (e.g. \"2.1.0\" vs \"2.3.1\").\n * Returns -1 if a < b, 0 if equal, 1 if a > b.\n */\nexport function compareSemver(a: string, b: string): number {\n const pa = a.split('.').map(Number);\n const pb = b.split('.').map(Number);\n for (let i = 0; i < 3; i++) {\n const va = pa[i] ?? 0;\n const vb = pb[i] ?? 0;\n if (va < vb) return -1;\n if (va > vb) return 1;\n }\n return 0;\n}\n","import { bytesToHex as nobleBytesToHex, hexToBytes as nobleHexToBytes } from '@noble/hashes/utils';\n\n/** Ensure hex string has 0x prefix */\nexport function ensure0x(hex: string): string {\n return hex.startsWith('0x') ? hex : `0x${hex}`;\n}\n\n/** Strip 0x prefix from hex string */\nexport function stripHex(hex: string): string {\n return hex.startsWith('0x') ? hex.slice(2) : hex;\n}\n\n/** Pad hex to 64 chars (32 bytes) with 0x prefix */\nexport function padHex64(hex: string): string {\n return `0x${stripHex(hex).padStart(64, '0')}`;\n}\n\n/**\n * Convert a hex string (with or without 0x prefix) to a Uint8Array.\n * Throws on invalid hex (non-hex characters, odd length).\n */\nexport function hexToBytes(hex: string): Uint8Array {\n return nobleHexToBytes(stripHex(hex));\n}\n\n/** Convert a Uint8Array to a hex string (no 0x prefix). */\nexport function bytesToHex(bytes: Uint8Array): string {\n return nobleBytesToHex(bytes);\n}\n","import { HardwareErrorCode } from '../types/errors';\n\n/**\n * Enrich a hardware error message with actionable recovery hints.\n * Shared across adapters (Ledger, Trezor, etc.).\n */\nexport function enrichErrorMessage(code: HardwareErrorCode, originalMessage: string): string {\n switch (code) {\n case HardwareErrorCode.PinInvalid:\n return `${originalMessage}. Please re-enter your PIN.`;\n case HardwareErrorCode.PinCancelled:\n return `${originalMessage}. PIN entry was cancelled.`;\n case HardwareErrorCode.DeviceBusy:\n return `${originalMessage}. The device is in use by another application. Close other wallet apps and try again.`;\n case HardwareErrorCode.DeviceDisconnected:\n return `${originalMessage}. Please reconnect the device and try again.`;\n case HardwareErrorCode.DeviceLocked:\n return `${originalMessage}. Please unlock your device and try again.`;\n case HardwareErrorCode.DeviceOneDeviceOnly:\n return `${originalMessage}. Disconnect the extra device and try again.`;\n case HardwareErrorCode.UserRejected:\n return `${originalMessage}. The request was rejected on the device.`;\n case HardwareErrorCode.WrongApp:\n return `${originalMessage}. Please open the correct app on your device.`;\n case HardwareErrorCode.AppNotInstalled:\n return `${originalMessage}. The required app is not installed on the device.`;\n case HardwareErrorCode.DeviceOutOfMemory:\n return `${originalMessage}. Not enough free space on the device. Please uninstall some apps and try again.`;\n case HardwareErrorCode.TransportNotAvailable:\n return `${originalMessage}. Ensure the device bridge/transport is available and running.`;\n case HardwareErrorCode.NetworkError:\n return `${originalMessage}. Network error — check your internet connection and try again.`;\n case HardwareErrorCode.FirmwareTooOld:\n return `${originalMessage}. Please update your device firmware.`;\n case HardwareErrorCode.DeviceNotInitialized:\n return `${originalMessage}. The device may need to be set up first.`;\n case HardwareErrorCode.OperationTimeout:\n return `${originalMessage}. The operation timed out. Please try again.`;\n case HardwareErrorCode.EvmBlindSigningRequired:\n return 'Ledger: Blind signing not enabled in Ethereum app.';\n case HardwareErrorCode.EvmClearSignPluginMissing:\n return 'Ledger: Required plugin not installed (install via Ledger Live).';\n case HardwareErrorCode.EvmDataTooLarge:\n return 'Ledger: Transaction data too large for device memory.';\n case HardwareErrorCode.EvmTxTypeNotSupported:\n return 'Ledger: Transaction type not supported by current Ethereum app.';\n case HardwareErrorCode.AppTooOld:\n return 'Ledger: App out of date (update via Ledger Live).';\n case HardwareErrorCode.SolanaBlindSigningRequired:\n return 'Blind signing disabled in the Solana app.';\n case HardwareErrorCode.TronCustomContractRequired:\n return 'Custom Contracts setting disabled in the Tron app.';\n case HardwareErrorCode.TronDataSigningRequired:\n return 'Transactions Data setting disabled in the Tron app.';\n case HardwareErrorCode.TronSignByHashRequired:\n return 'Sign by Hash setting disabled in the Tron app.';\n case HardwareErrorCode.BtcWalletPolicyHmacMismatch:\n return 'Wallet policy not registered or HMAC mismatch.';\n case HardwareErrorCode.BtcUnexpectedState:\n return 'Signing aborted due to unexpected device state.';\n default:\n return originalMessage;\n }\n}\n","import type { Response } from '../types/response';\n\n/**\n * Generic batch call with progress reporting.\n * If any single call fails, returns the failure immediately.\n */\nexport async function batchCall<TParam, TResult>(\n params: TParam[],\n callFn: (p: TParam) => Promise<Response<TResult>>,\n onProgress?: (progress: { index: number; total: number }) => void\n): Promise<Response<TResult[]>> {\n const results: TResult[] = [];\n for (let i = 0; i < params.length; i++) {\n const result = await callFn(params[i]);\n if (!result.success) {\n return result;\n }\n results.push(result.payload);\n onProgress?.({ index: i, total: params.length });\n }\n return { success: true, payload: results };\n}\n"],"mappings":"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","names":["bytesToHex","HardwareErrorCode","EConnectorInteraction","import_utils","nobleHexToBytes","bytesToHex","nobleBytesToHex"]}
package/dist/index.mjs CHANGED
@@ -23,6 +23,7 @@ var HardwareErrorCode = /* @__PURE__ */ ((HardwareErrorCode2) => {
23
23
  HardwareErrorCode2[HardwareErrorCode2["TransportNotAvailable"] = 10302] = "TransportNotAvailable";
24
24
  HardwareErrorCode2[HardwareErrorCode2["DevicePermissionDenied"] = 10303] = "DevicePermissionDenied";
25
25
  HardwareErrorCode2[HardwareErrorCode2["BlePairingTimeout"] = 10304] = "BlePairingTimeout";
26
+ HardwareErrorCode2[HardwareErrorCode2["NetworkError"] = 10305] = "NetworkError";
26
27
  HardwareErrorCode2[HardwareErrorCode2["PinInvalid"] = 10400] = "PinInvalid";
27
28
  HardwareErrorCode2[HardwareErrorCode2["PinCancelled"] = 10401] = "PinCancelled";
28
29
  HardwareErrorCode2[HardwareErrorCode2["PassphraseRejected"] = 10402] = "PassphraseRejected";
@@ -54,6 +55,14 @@ var ORPHAN_ELIGIBLE_ERROR_CODES = [
54
55
  10303 /* DevicePermissionDenied */,
55
56
  10304 /* BlePairingTimeout */
56
57
  ];
58
+ function createHwkError(payload) {
59
+ return Object.assign(new Error(payload.message), {
60
+ code: payload.code,
61
+ ...payload._tag !== void 0 && { _tag: payload._tag },
62
+ ...payload.appName !== void 0 && { appName: payload.appName },
63
+ ...payload.params !== void 0 && { params: payload.params }
64
+ });
65
+ }
57
66
 
58
67
  // src/types/response.ts
59
68
  function success(payload) {
@@ -528,6 +537,8 @@ function enrichErrorMessage(code, originalMessage) {
528
537
  return `${originalMessage}. Not enough free space on the device. Please uninstall some apps and try again.`;
529
538
  case 10302 /* TransportNotAvailable */:
530
539
  return `${originalMessage}. Ensure the device bridge/transport is available and running.`;
540
+ case 10305 /* NetworkError */:
541
+ return `${originalMessage}. Network error \u2014 check your internet connection and try again.`;
531
542
  case 10200 /* FirmwareTooOld */:
532
543
  return `${originalMessage}. Please update your device firmware.`;
533
544
  case 10104 /* DeviceNotInitialized */:
@@ -596,6 +607,7 @@ export {
596
607
  bytesToHex2 as bytesToHex,
597
608
  compareSemver,
598
609
  createBridgedConnector,
610
+ createHwkError,
599
611
  deriveDeviceFingerprint,
600
612
  enrichErrorMessage,
601
613
  ensure0x,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types/errors.ts","../src/types/response.ts","../src/types/fingerprint.ts","../src/events/device.ts","../src/events/ui-request.ts","../src/events/sdk.ts","../src/utils/DeviceJobQueue.ts","../src/types/connector.ts","../src/utils/TypedEventEmitter.ts","../src/utils/UiRequestRegistry.ts","../src/utils/semver.ts","../src/utils/hex.ts","../src/utils/errorMessages.ts","../src/utils/batchCall.ts"],"sourcesContent":["/**\n * HWK HardwareErrorCode — independent namespace from the legacy\n * `@onekeyfe/shared` HardwareErrorCode (which occupies 0-902).\n *\n * All HWK codes are 5-digit (>= 10000) so the two tables never collide\n * even if either side grows. Each sub-category gets a 100-slot block.\n *\n * 10000-10099 Generic / cross-cutting primitives\n * 10100-10199 Device state\n * 10200-10299 Firmware\n * 10300-10399 Transport + OS-level permission\n * 10400-10499 PIN / Passphrase\n * 10500-10599 App lifecycle (wrong app, not open, too old)\n * 10600-10999 RESERVED — future adapter-level categories\n *\n * 11000-11099 EVM APDU (reactive mapping)\n * 11100-11199 Solana APDU\n * 11200-11299 Tron APDU\n * 11300-11399 BTC APDU\n * 11400-11999 RESERVED — future chain APDU blocks (100 per chain)\n *\n * 12000-99999 RESERVED — future major categories\n */\nexport enum HardwareErrorCode {\n // --- 10000s Generic ---\n UnknownError = 10000,\n UserRejected = 10001,\n InvalidParams = 10002,\n OperationTimeout = 10003,\n MethodNotSupported = 10004,\n /** User dismissed in-app cancel UI. Distinct from UserRejected (on-device). */\n UserAborted = 10005,\n\n // --- 10100s Device state ---\n DeviceNotFound = 10100,\n DeviceDisconnected = 10101,\n DeviceBusy = 10102,\n DeviceLocked = 10103,\n DeviceNotInitialized = 10104,\n DeviceInBootloader = 10105,\n DeviceMismatch = 10106,\n /** Chain app wedged (e.g. Ledger BTC 0x6901). User must exit app on device. */\n DeviceAppStuck = 10107,\n /** Vendor (Ledger / Trezor) doesn't support the chain at all. */\n ChainNotSupported = 10108,\n /** Current operation supports only one connected device. */\n DeviceOneDeviceOnly = 10109,\n\n // --- 10200s Firmware ---\n FirmwareTooOld = 10200,\n FirmwareUpdateRequired = 10201,\n\n // --- 10300s Transport + permission ---\n TransportError = 10300,\n BridgeNotFound = 10301,\n TransportNotAvailable = 10302,\n /**\n * OS-level permission (Bluetooth / USB / etc.) — denied, blocked,\n * unavailable, or dismissed. Consumers surface a single \"please grant\n * permission\" toast and let the user retry manually.\n */\n DevicePermissionDenied = 10303,\n /**\n * BLE SMP pairing did not complete within the GATT bonding window.\n * GATT connected but the device didn't acknowledge SMP — typically\n * because the user didn't confirm the passkey on the device, or the\n * device went out of range mid-pairing. Distinct from OperationTimeout\n * (generic) and from DeviceLocked (Secure Element actually locked).\n */\n BlePairingTimeout = 10304,\n\n // --- 10400s PIN / Passphrase ---\n PinInvalid = 10400,\n PinCancelled = 10401,\n PassphraseRejected = 10402,\n\n // --- 10500s App lifecycle ---\n /** Chain app NOT INSTALLED on device. User must install via Ledger Live. */\n AppNotInstalled = 10500,\n WrongApp = 10501,\n /** 0x911c Command code not supported — app predates current SDK. */\n AppTooOld = 10502,\n /** Not enough free storage for install/update; user must uninstall apps first. */\n DeviceOutOfMemory = 10503,\n\n // --- 11000s EVM (Ledger Ethereum App) APDU-specific ---\n /** 0x6a80 Invalid data — observed on blindSignTransactionFallback when the\n * user has not enabled Blind signing on the device. */\n EvmBlindSigningRequired = 11000,\n /** 0x6984 Plugin not installed */\n EvmClearSignPluginMissing = 11001,\n /** 0x6a84 Insufficient memory (typical on Nano S with large calldata) */\n EvmDataTooLarge = 11002,\n /** 0x6501 TransactionType not supported (app too old for EIP-1559 / blob / 7702) */\n EvmTxTypeNotSupported = 11003,\n\n // --- 11100s Solana ---\n /** 0x6808 Blind signing disabled for this instruction. */\n SolanaBlindSigningRequired = 11100,\n\n // --- 11200s Tron ---\n /** 0x6a8d Custom Contracts setting disabled (blocks TRC-20 etc.). */\n TronCustomContractRequired = 11200,\n /** 0x6a8b Transactions Data setting disabled. */\n TronDataSigningRequired = 11201,\n /** 0x6a8c Sign by Hash setting disabled (hash-signing fallback). */\n TronSignByHashRequired = 11202,\n\n // --- 11300s BTC ---\n /** 0xb008 Wallet policy HMAC mismatch or not registered. */\n BtcWalletPolicyHmacMismatch = 11300,\n /** 0xb007 Aborted due to unexpected state (malformed PSBT / missing UTXO). */\n BtcUnexpectedState = 11301,\n}\n\n/**\n * Device-level failures the SDK cannot self-recover from — affect the entire\n * batch (vs per-chain failures like AppNotInstalled / WrongApp which soft-\n * skip in onboarding). Combined with `accounts.length === 0`, signals\n * genuine orphan. Also reused as the batch-abort whitelist for HWK.\n * Single source of truth.\n *\n * UserRejected (device-side reject) is included: pressing reject is an\n * explicit \"I don't consent\" — continuing the batch to ask again on the\n * next chain is harassment, not helpful.\n */\nexport const ORPHAN_ELIGIBLE_ERROR_CODES: number[] = [\n HardwareErrorCode.UserAborted,\n HardwareErrorCode.UserRejected,\n HardwareErrorCode.DeviceNotFound,\n HardwareErrorCode.DeviceDisconnected,\n HardwareErrorCode.DeviceMismatch,\n HardwareErrorCode.DeviceAppStuck,\n HardwareErrorCode.DeviceOneDeviceOnly,\n HardwareErrorCode.TransportError,\n HardwareErrorCode.DevicePermissionDenied,\n HardwareErrorCode.BlePairingTimeout,\n];\n","import type { HardwareErrorCode } from './errors';\n\nexport interface Success<T> {\n success: true;\n payload: T;\n}\n\nexport interface Failure {\n success: false;\n payload: {\n error: string;\n code: HardwareErrorCode;\n params?: Record<string, unknown>;\n };\n}\n\nexport type Response<T> = Success<T> | Failure;\n\nexport function success<T>(payload: T): Success<T> {\n return { success: true, payload };\n}\n\nexport function failure(\n code: HardwareErrorCode,\n error: string,\n params?: Record<string, unknown>\n): Failure {\n return {\n success: false,\n payload: { error, code, ...(params ? { params } : {}) },\n };\n}\n","/**\n * Chain fingerprint utilities for device identity verification.\n *\n * Ledger devices have ephemeral IDs that change every session.\n * To verify that the same seed/device is connected, we derive an address\n * at a fixed path (account 0, index 0) and hash it into a stable \"chain fingerprint\".\n */\nimport { sha256 } from '@noble/hashes/sha256';\nimport { bytesToHex, utf8ToBytes } from '@noble/hashes/utils';\n\n/**\n * Fixed derivation paths used to generate chain fingerprints.\n * Uses standard index 0 — Ledger firmware shows device confirmation for\n * non-standard paths (e.g., index=100), which would interrupt wallet creation.\n * The address is hashed into a 16-char fingerprint, not exposed directly.\n * - EVM: cointype 60 (Ledger ETH App only supports 60)\n * - BTC: cointype 1 (testnet)\n * - SOL: cointype 501, standard 3-level hardened\n */\nexport const CHAIN_FINGERPRINT_PATHS: Record<ChainForFingerprint, string> = {\n evm: \"m/44'/60'/0'/0/0\",\n // BTC: account-level path (3 levels), mainnet cointype 0.\n // Cointype 1 (testnet) is rejected by some Ledger BTC App configurations.\n btc: \"m/44'/0'/0'\",\n sol: \"m/44'/501'/0'\",\n tron: \"m/44'/195'/0'/0/0\",\n};\n\nexport type ChainForFingerprint = 'evm' | 'btc' | 'sol' | 'tron';\n\n/**\n * 16-char SHA-256 fingerprint for device-identity verification.\n * Callers must canonicalize input (e.g. EVM address → lowercase) —\n * encoding variations otherwise cause false DeviceMismatch.\n */\nexport function deriveDeviceFingerprint(value: string): string {\n return bytesToHex(sha256(utf8ToBytes(value))).slice(0, 16);\n}\n","export const DEVICE_EVENT = 'DEVICE_EVENT';\n\n/** Events originating from the hardware device. */\nexport const DEVICE = {\n CONNECT: 'device-connect',\n DISCONNECT: 'device-disconnect',\n CHANGED: 'device-changed',\n} as const;\n","import type { QrResponseData } from '../types/qr';\n\nexport const UI_EVENT = 'UI_EVENT';\n\nexport const UI_REQUEST = {\n REQUEST_PIN: 'ui-request-pin',\n REQUEST_PASSPHRASE: 'ui-request-passphrase',\n REQUEST_PASSPHRASE_ON_DEVICE: 'ui-request-passphrase-on-device',\n REQUEST_BUTTON: 'ui-request-button',\n REQUEST_QR_DISPLAY: 'ui-request-qr-display',\n REQUEST_QR_SCAN: 'ui-request-qr-scan',\n REQUEST_DEVICE_PERMISSION: 'ui-request-device-permission',\n REQUEST_SELECT_DEVICE: 'ui-request-select-device',\n REQUEST_DEVICE_CONNECT: 'ui-request-device-connect',\n // Ledger BTC App: account index >= 100 requires display=true. Adapter asks\n // the user once per session before promoting the call.\n REQUEST_BTC_HIGH_INDEX_CONFIRM: 'ui-request-btc-high-index-confirm',\n // Required app is not installed; with autoInstallApp on, ask the user\n // whether to install it before retrying the operation.\n REQUEST_INSTALL_APP: 'ui-request-install-app',\n CLOSE_UI_WINDOW: 'ui-close',\n DEVICE_PROGRESS: 'ui-device_progress',\n FIRMWARE_PROGRESS: 'ui-firmware-progress',\n FIRMWARE_TIP: 'ui-firmware-tip',\n} as const;\n\nexport const UI_RESPONSE = {\n RECEIVE_PIN: 'receive-pin',\n RECEIVE_PASSPHRASE: 'receive-passphrase',\n RECEIVE_PASSPHRASE_ON_DEVICE: 'receive-passphrase-on-device',\n RECEIVE_QR_RESPONSE: 'receive-qr-response',\n RECEIVE_SELECT_DEVICE: 'receive-select-device',\n RECEIVE_DEVICE_CONNECT: 'receive-device-connect',\n RECEIVE_DEVICE_PERMISSION: 'receive-device-permission',\n RECEIVE_BTC_HIGH_INDEX_CONFIRM: 'receive-btc-high-index-confirm',\n RECEIVE_INSTALL_APP: 'receive-install-app',\n CANCEL: 'cancel',\n} as const;\n\nexport type DevicePermissionDeniedReason =\n | 'bluetoothTurnedOff'\n | 'permissionDenied'\n | (string & Record<never, never>);\n\nexport type DevicePermissionResponse = {\n granted: boolean;\n reason?: DevicePermissionDeniedReason;\n message?: string;\n};\n\nexport type UiResponseEvent =\n | {\n type: typeof UI_RESPONSE.RECEIVE_PIN;\n payload: string;\n }\n | {\n type: typeof UI_RESPONSE.RECEIVE_PASSPHRASE;\n payload: {\n value: string;\n passphraseOnDevice?: boolean;\n save?: boolean;\n };\n }\n | {\n type: typeof UI_RESPONSE.RECEIVE_PASSPHRASE_ON_DEVICE;\n payload?: undefined;\n }\n | {\n type: typeof UI_RESPONSE.RECEIVE_QR_RESPONSE;\n payload: QrResponseData;\n }\n | {\n // sdkConnectId echoes one of the DeviceInfo.connectId values emitted in\n // the REQUEST_SELECT_DEVICE event's `devices` list. Scope is the current\n // search session; may be ephemeral (e.g. Ledger USB DMK UUID).\n type: typeof UI_RESPONSE.RECEIVE_SELECT_DEVICE;\n payload: { sdkConnectId: string };\n }\n | {\n type: typeof UI_RESPONSE.RECEIVE_DEVICE_CONNECT;\n payload: { confirmed: boolean };\n }\n | {\n type: typeof UI_RESPONSE.RECEIVE_DEVICE_PERMISSION;\n payload: DevicePermissionResponse;\n }\n | {\n type: typeof UI_RESPONSE.RECEIVE_BTC_HIGH_INDEX_CONFIRM;\n payload: { confirmed: boolean };\n }\n | {\n type: typeof UI_RESPONSE.RECEIVE_INSTALL_APP;\n payload: { confirmed: boolean };\n }\n | {\n type: typeof UI_RESPONSE.CANCEL;\n payload?: undefined;\n };\n","/** Events generated by SDK internal detection (not from hardware directly). */\nexport const SDK = {\n DEVICE_STUCK: 'device-stuck',\n DEVICE_UNRESPONSIVE: 'device-unresponsive',\n DEVICE_RECOVERED: 'device-recovered',\n DEVICE_INTERACTION: 'device-interaction',\n} as const;\n","/**\n * Pure FIFO job queue. Every enqueue chains onto the tail; jobs run one at\n * a time across all devices. The queue is intentionally passive — it does\n * NOT decide whether to interrupt or ask the user. Those are application-\n * layer concerns owned by the caller (e.g. a UI button handler that wants\n * to ask \"device is busy, interrupt current?\" before submitting). The\n * queue exposes inspection (`getActiveJob`) and explicit cancellation\n * (`cancelActive` / `cancelAll`) so callers can implement those policies\n * synchronously, without racing against in-flight enqueues.\n */\n\nexport interface JobOptions {\n label?: string;\n rejectIfBusy?: boolean;\n busyError?: Error;\n}\n\nexport interface ActiveJobInfo {\n deviceId: string;\n label?: string;\n startedAt: number;\n}\n\ninterface ActiveJob {\n deviceId: string;\n label?: string;\n abortController: AbortController;\n startedAt: number;\n}\n\nexport class DeviceJobQueue {\n private _tail: Promise<unknown> = Promise.resolve();\n\n private _active: ActiveJob | null = null;\n\n private readonly _jobs = new Map<object, { deviceId: string }>();\n\n /** Incremented on clear() so queued-but-not-yet-running jobs detect invalidation. */\n private _generation = 0;\n\n private readonly _generationCancelReasons = new Map<number, Error>();\n\n /**\n * Enqueue a job. Runs after every previously-enqueued job has settled.\n * `deviceId` is a label only — used by inspection / cancellation routing.\n */\n async enqueue<T>(\n deviceId: string,\n job: (signal: AbortSignal) => Promise<T>,\n options: JobOptions = {}\n ): Promise<T> {\n if (options.rejectIfBusy && this._jobs.size > 0) {\n throw options.busyError ?? new Error('Device is busy');\n }\n\n const ac = new AbortController();\n const gen = this._generation;\n const prev = this._tail;\n const jobToken = {};\n const activeJob: ActiveJob = {\n deviceId,\n label: options.label,\n abortController: ac,\n startedAt: Date.now(),\n };\n this._jobs.set(jobToken, { deviceId });\n\n const next = prev\n .catch(() => {})\n .then(async () => {\n if (this._generation !== gen) {\n throw (\n this._generationCancelReasons.get(gen) ?? new Error('Job cancelled: queue was cleared')\n );\n }\n this._active = activeJob;\n try {\n return await job(ac.signal);\n } finally {\n // Identity guard: a previous job's deferred finally must not\n // null out a successor's `_active`.\n if (this._active === activeJob) {\n this._active = null;\n }\n }\n })\n .finally(() => {\n this._jobs.delete(jobToken);\n });\n\n this._tail = next.catch(() => {});\n return next;\n }\n\n /** Cancel the active job. If `deviceId` is given, only cancels when it matches. */\n cancelActive(deviceId?: string): boolean {\n if (!this._active) return false;\n if (deviceId && this._active.deviceId !== deviceId) return false;\n this._active.abortController.abort(new Error('Manually cancelled'));\n return true;\n }\n\n /** Force cancel the active job. `reason` becomes signal.reason. */\n forceCancelActive(deviceId?: string, reason?: Error): boolean {\n if (!this._active) return false;\n if (deviceId && this._active.deviceId !== deviceId) return false;\n this._active.abortController.abort(reason ?? new Error('Force cancelled for recovery'));\n return true;\n }\n\n /** Cancel the active job (alias for callers that previously needed multi-device cancel). */\n cancelAllActive(reason?: Error): void {\n if (!this._active) return;\n this._active.abortController.abort(reason ?? new Error('Cancelled by cancelAllActive'));\n }\n\n /** Cancel the active job and invalidate queued jobs that have not started. */\n cancelActiveAndPending(deviceId?: string, reason?: Error): boolean {\n if (deviceId && this._active && this._active.deviceId !== deviceId) {\n return false;\n }\n this.clear(reason ?? new Error('Cancelled by cancelActiveAndPending'));\n return true;\n }\n\n /** Get info about the currently active job, or null if idle. */\n getActiveJob(deviceId?: string): ActiveJobInfo | null {\n if (!this._active) return null;\n if (deviceId && this._active.deviceId !== deviceId) return null;\n return {\n deviceId: this._active.deviceId,\n label: this._active.label,\n startedAt: this._active.startedAt,\n };\n }\n\n /** True if any job is currently running. */\n isBusy(): boolean {\n return this._jobs.size > 0;\n }\n\n clear(reason?: Error): void {\n const cancelledGeneration = this._generation;\n this._generation++;\n const cancelReason = reason ?? new Error('Job cancelled: queue was cleared');\n this._generationCancelReasons.set(cancelledGeneration, cancelReason);\n for (const generation of this._generationCancelReasons.keys()) {\n if (generation < this._generation - 10) {\n this._generationCancelReasons.delete(generation);\n }\n }\n if (this._active) {\n this._active.abortController.abort(cancelReason);\n }\n }\n}\n","import type { ConnectionType, DeviceCapabilities, DeviceInfo, VendorType } from './device';\nimport type { UiResponseEvent } from '../events/ui-request';\n\n// =====================================================================\n// Connector types — transport-level abstraction for device communication\n// =====================================================================\n\n/**\n * Minimal device info returned during discovery (searchDevices).\n * At scan time, full DeviceInfo fields like firmwareVersion are not yet available.\n */\nexport interface ConnectorDevice {\n connectId: string;\n deviceId: string;\n name: string;\n /** Machine model id (e.g. \"nanoX\"). */\n model?: string;\n /** Human-readable model name (e.g. \"Ledger Nano X\"). */\n modelName?: string;\n /** BLE signal strength (BLE only). */\n rssi?: number | null;\n /** BLE connectable flag (BLE only). */\n isConnectable?: boolean | null;\n /** USB serial number (USB only). */\n serialNumber?: string;\n\n /** Device capabilities — available from scan time */\n capabilities?: DeviceCapabilities;\n}\n\nexport interface ConnectorSession {\n sessionId: string;\n deviceInfo: DeviceInfo;\n}\n\n// =====================================================================\n// Connector call result — device errors travel as DATA, not exceptions\n//\n// `IConnector.call` never throws for device-level failures. It resolves a\n// discriminated result so the failure crosses any process boundary\n// (IHardwareBridge / extension offscreen↔SW) as plain `data`. This mirrors\n// the OneKey HD-SDK `IDeviceResponseResult` contract.\n//\n// WHY: when a thrown Error crosses the extension JsBridge it is run through\n// `toPlainError`, a fixed field whitelist that drops custom own-properties\n// (e.g. `appName`). Returning the failure as data keeps every field intact.\n//\n// Contract for `ConnectorSerializedError`: only `message` / `code` /\n// `errorCode` live at the top level; ALL other domain fields (`appName`,\n// `_tag`, `statusCode`, …) are nested under `params`.\n// =====================================================================\n\n/**\n * Vendor-agnostic bag of extra error fields. Known keys are documented for\n * discoverability; the index signature keeps it open so any connector can\n * carry vendor-specific data without losing it across the bridge.\n */\nexport interface ConnectorErrorParams {\n /** Vendor SDK error tag (e.g. Ledger DMK `_tag`). */\n _tag?: string;\n /** App involved, e.g. the Ledger app being opened/installed. */\n appName?: string;\n /** Transport / APDU status code (string or number depending on vendor). */\n statusCode?: unknown;\n /**\n * Shallow snapshot of a nested cause. A raw Error does not survive JSON\n * serialization (its `message`/`stack` are non-enumerable), so recovery\n * predicates that recurse into a cause get this plain-object copy instead.\n */\n originalError?: {\n message?: string;\n code?: number;\n errorCode?: string;\n statusCode?: unknown;\n _tag?: string;\n };\n [key: string]: unknown;\n}\n\nexport interface ConnectorSerializedError {\n message: string;\n code?: number;\n errorCode?: string;\n params?: ConnectorErrorParams;\n}\n\nexport type ConnectorCallResult =\n | { success: true; payload: unknown }\n | { success: false; error: ConnectorSerializedError };\n\nexport type ConnectorEventType = 'device-connect' | 'device-disconnect' | 'ui-request' | 'ui-event';\n\n/**\n * Interaction event types emitted via 'ui-event'.\n * These map to user-facing prompts (confirm on device, open app, etc.).\n */\nexport enum EConnectorInteraction {\n /** Adapter is actively searching for the device (no session yet) */\n Searching = 'searching',\n /** Device requires user to open a specific app */\n ConfirmOpenApp = 'confirm-open-app',\n /** Device requires user to unlock */\n UnlockDevice = 'unlock-device',\n /** Device needs user to confirm on device (sign, verify, etc.) */\n ConfirmOnDevice = 'confirm-on-device',\n /** Previous interaction completed — clear UI prompt */\n InteractionComplete = 'interaction-complete',\n /**\n * OS-level Ledger app install progress. `progress` is a 0..1 fraction\n * reported by DMK's InstallOrUpdateAppsDeviceAction. Emitted from inside\n * the connector so the progress callback ref never has to cross the\n * IHardwareBridge boundary.\n */\n AppInstallProgress = 'app-install-progress',\n}\n\n// Discriminated union: most variants only carry `sessionId`, but\n// AppInstallProgress also carries `appName` + `progress`. Searching has no\n// session yet so it carries an empty `sessionId`.\nexport type ConnectorUiEvent =\n | { type: EConnectorInteraction.Searching; payload: { sessionId: string } }\n | { type: EConnectorInteraction.ConfirmOpenApp; payload: { sessionId: string } }\n | { type: EConnectorInteraction.UnlockDevice; payload: { sessionId: string } }\n | { type: EConnectorInteraction.ConfirmOnDevice; payload: { sessionId: string } }\n | { type: EConnectorInteraction.InteractionComplete; payload: { sessionId: string } }\n | {\n type: EConnectorInteraction.AppInstallProgress;\n payload: { sessionId: string; appName: string; progress: number };\n };\n\nexport interface ConnectorEventMap {\n 'device-connect': { device: ConnectorDevice };\n 'device-disconnect': { connectId: string };\n 'ui-request': { type: string; payload?: unknown };\n 'ui-event': ConnectorUiEvent;\n}\n\nexport interface IConnector {\n /** Physical connection type this connector uses. Fixed at construction. */\n readonly connectionType: ConnectionType;\n\n searchDevices(): Promise<ConnectorDevice[]>;\n connect(deviceId?: string): Promise<ConnectorSession>;\n disconnect(sessionId: string): Promise<void>;\n // `call` resolves a discriminated result; device-level failures are returned\n // as data, never thrown (see ConnectorCallResult). Only `call` uses this\n // contract because it is the one method that carries rich, vendor-specific\n // domain errors across the IHardwareBridge boundary, where a thrown Error\n // would be stripped by the host bridge's error whitelist. The other methods\n // surface plain operational failures and still reject normally.\n call(sessionId: string, method: string, params: unknown): Promise<ConnectorCallResult>;\n cancel(sessionId: string): Promise<void>;\n\n /** Send a UI response (e.g. PIN, passphrase) to the device. */\n uiResponse(response: UiResponseEvent): void;\n\n on<K extends ConnectorEventType>(event: K, handler: (data: ConnectorEventMap[K]) => void): void;\n off<K extends ConnectorEventType>(event: K, handler: (data: ConnectorEventMap[K]) => void): void;\n\n reset(): void;\n}\n\n// =====================================================================\n// Hardware bridge — generic forwarding interface for cross-boundary IConnector\n//\n// The same shape works across any process / context boundary that needs to\n// expose a multi-vendor backend behind a single-vendor IConnector facade:\n// - Electron (renderer ↔ preload/main via contextBridge)\n// - Browser Extension (popup/content ↔ background/offscreen via chrome.runtime)\n// - React Native (JS ↔ native module via NativeModules)\n// - Web Worker / iframe (postMessage)\n//\n// Each method takes a `vendor` discriminator so a single bridge implementation\n// can multiplex across vendors (ledger, trezor, ...).\n// =====================================================================\n\nexport interface IHardwareBridge {\n searchDevices(params: { vendor: VendorType }): Promise<ConnectorDevice[]>;\n connect(params: { vendor: VendorType; deviceId?: string }): Promise<ConnectorSession>;\n disconnect(params: { vendor: VendorType; sessionId: string }): Promise<void>;\n call(params: {\n vendor: VendorType;\n sessionId: string;\n method: string;\n callParams: unknown;\n }): Promise<ConnectorCallResult>;\n cancel(params: { vendor: VendorType; sessionId: string }): Promise<void>;\n uiResponse(params: { vendor: VendorType; response: UiResponseEvent }): void;\n reset(params: { vendor: VendorType }): void;\n\n /** Register an event handler for connector events forwarded across the bridge. */\n onEvent(\n params: { vendor: VendorType },\n handler: (event: { type: ConnectorEventType; data: unknown }) => void\n ): void;\n\n /** Unregister a previously registered event handler. */\n offEvent(\n params: { vendor: VendorType },\n handler: (event: { type: ConnectorEventType; data: unknown }) => void\n ): void;\n}\n\n/**\n * Adapt an IHardwareBridge (multi-vendor backend) into a single-vendor IConnector.\n * Every IConnector method becomes a transparent forward to bridge.<method>({ vendor, ... }).\n * Events are forwarded via bridge.onEvent / offEvent.\n *\n * Use this anywhere the actual hardware lives behind a process / context boundary\n * (Electron main, extension background, native module, worker, iframe).\n */\nexport function createBridgedConnector(\n vendor: VendorType,\n connectionType: ConnectionType,\n bridge: IHardwareBridge\n): IConnector {\n // Keyed by (event, handler). A flat handler-only map would collide when the\n // same function is registered for multiple events — second .on() would\n // overwrite the first bridge handler reference, leaking it permanently.\n type UserHandler = (data: ConnectorEventMap[ConnectorEventType]) => void;\n type BridgeHandler = (event: { type: ConnectorEventType; data: unknown }) => void;\n const handlerMap = new Map<ConnectorEventType, Map<UserHandler, BridgeHandler>>();\n\n return {\n connectionType,\n searchDevices: () => bridge.searchDevices({ vendor }),\n connect: deviceId => bridge.connect({ vendor, deviceId }),\n disconnect: sessionId => bridge.disconnect({ vendor, sessionId }),\n call: (sessionId, method, callParams) => bridge.call({ vendor, sessionId, method, callParams }),\n cancel: sessionId => bridge.cancel({ vendor, sessionId }),\n uiResponse: response => bridge.uiResponse({ vendor, response }),\n on: (event, handler) => {\n const bridgeHandler: BridgeHandler = e => {\n if (e.type === event) {\n handler(e.data as ConnectorEventMap[typeof event]);\n }\n };\n let inner = handlerMap.get(event);\n if (!inner) {\n inner = new Map();\n handlerMap.set(event, inner);\n }\n inner.set(handler as UserHandler, bridgeHandler);\n bridge.onEvent({ vendor }, bridgeHandler);\n },\n off: (event, handler) => {\n const inner = handlerMap.get(event);\n const bridgeHandler = inner?.get(handler as UserHandler);\n if (!bridgeHandler || !inner) return;\n bridge.offEvent({ vendor }, bridgeHandler);\n inner.delete(handler as UserHandler);\n if (inner.size === 0) handlerMap.delete(event);\n },\n reset: () => bridge.reset({ vendor }),\n };\n}\n\n// =====================================================================\n// ConnectorCallResult error (de)serialization — the canonical, vendor-agnostic\n// helpers every IConnector implementation / adapter should use, so the\n// \"errors as data\" contract is identical across vendors.\n// =====================================================================\n\nconst SERIALIZED_ERROR_TOP_LEVEL_KEYS = new Set([\n 'message',\n 'code',\n 'errorCode',\n 'stack',\n 'params',\n]);\n\n/**\n * Flatten a thrown error into the cross-boundary-safe `ConnectorSerializedError`\n * shape. `message`/`code`/`errorCode` are lifted to the top level; every other\n * own-enumerable field is copied into `params` so NO domain data is lost when\n * the result crosses a host bridge (which may run thrown errors through a\n * field whitelist). A nested `originalError` is shallow-snapshotted because a\n * raw Error does not survive JSON serialization.\n */\nexport function serializeConnectorError(err: unknown): ConnectorSerializedError {\n if (!err || typeof err !== 'object') {\n return { message: typeof err === 'string' ? err : 'Unknown error' };\n }\n const e = err as Record<string, unknown>;\n const message = typeof e.message === 'string' ? e.message : 'Unknown error';\n const code = typeof e.code === 'number' ? e.code : undefined;\n const errorCode = e.errorCode != null ? String(e.errorCode) : undefined;\n\n const params: ConnectorErrorParams = {};\n // Flatten an existing `params` bag, then copy every other own field (so\n // vendor-specific keys like `_tag` / `statusCode` / `appName` / step context\n // are preserved without being named here).\n if (e.params && typeof e.params === 'object') {\n Object.assign(params, e.params as Record<string, unknown>);\n }\n for (const key of Object.keys(e)) {\n if (!SERIALIZED_ERROR_TOP_LEVEL_KEYS.has(key)) {\n params[key] = e[key];\n }\n }\n const orig = e.originalError;\n if (orig && typeof orig === 'object') {\n const o = orig as Record<string, unknown>;\n params.originalError = {\n message: typeof o.message === 'string' ? o.message : undefined,\n code: typeof o.code === 'number' ? o.code : undefined,\n errorCode: o.errorCode != null ? String(o.errorCode) : undefined,\n statusCode: o.statusCode,\n _tag: typeof o._tag === 'string' ? o._tag : undefined,\n };\n }\n\n // The result crosses host bridges via JSON.stringify. Drop any single field\n // that isn't JSON-safe (circular ref / non-serializable) so a pathological\n // error degrades to \"one field missing\" instead of crashing the transport.\n for (const key of Object.keys(params)) {\n try {\n JSON.stringify(params[key]);\n } catch {\n delete params[key];\n }\n }\n\n return {\n message,\n ...(code !== undefined ? { code } : {}),\n ...(errorCode !== undefined ? { errorCode } : {}),\n ...(Object.keys(params).length ? { params } : {}),\n };\n}\n\n/**\n * Inverse of `serializeConnectorError`: rebuild a flat Error instance, lifting\n * `params.*` back to own-properties so existing throw-based classifiers/recovery\n * logic (which read `err._tag` / `err.code` / `err.appName` / …) keep working\n * unchanged. The Result shape stays confined to the connector boundary.\n */\nexport function rehydrateConnectorError(error: ConnectorSerializedError): Error {\n const { message, code, errorCode, params } = error;\n return Object.assign(new Error(message), {\n ...(code !== undefined ? { code } : {}),\n ...(errorCode !== undefined ? { errorCode } : {}),\n ...(params ?? {}),\n });\n}\n","/**\n * Minimal typed event emitter using Map<string, Set<listener>>.\n * Each adapter uses this for device events (connect, disconnect, pin, etc.).\n *\n * TMap is a record mapping event name strings to their payload types.\n * Example:\n * type MyEvents = { 'connect': { id: string }; 'disconnect': { id: string } };\n * const emitter = new TypedEventEmitter<MyEvents>();\n * emitter.on('connect', (data) => { data.id }); // data is { id: string }\n *\n * For backward compatibility, TMap defaults to Record<string, any> so that\n * existing code using `new TypedEventEmitter<SomeUnionType>()` still compiles.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport class TypedEventEmitter<TMap extends Record<string, any> = Record<string, any>> {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private readonly _listeners = new Map<string, Set<(event: any) => void>>();\n\n on<K extends keyof TMap & string>(event: K, listener: (event: TMap[K]) => void): void;\n\n on(event: string, listener: (event: any) => void): void;\n\n on(event: string, listener: (event: any) => void): void {\n let set = this._listeners.get(event);\n if (!set) {\n set = new Set();\n this._listeners.set(event, set);\n }\n set.add(listener);\n }\n\n off<K extends keyof TMap & string>(event: K, listener: (event: TMap[K]) => void): void;\n\n off(event: string, listener: (event: any) => void): void;\n\n off(event: string, listener: (event: any) => void): void {\n const set = this._listeners.get(event);\n if (set) {\n set.delete(listener);\n if (set.size === 0) this._listeners.delete(event);\n }\n }\n\n emit<K extends keyof TMap & string>(event: K, data: TMap[K]): void;\n\n emit(event: string, data: unknown): void;\n\n emit(event: string, data: unknown): void {\n const set = this._listeners.get(event);\n if (set) {\n for (const listener of set) listener(data);\n }\n }\n\n removeAllListeners(): void {\n this._listeners.clear();\n }\n}\n","import { UI_REQUEST, UI_RESPONSE } from '../events/ui-request';\n\n/** 10 min — every UI request is human-in-the-loop; bias toward \"wait long\". */\nexport const UI_REQUEST_DEFAULT_TIMEOUT_MS = 600_000;\n\nconst RESPONSE_TO_REQUEST: Record<string, string> = {\n [UI_RESPONSE.RECEIVE_PIN]: UI_REQUEST.REQUEST_PIN,\n [UI_RESPONSE.RECEIVE_PASSPHRASE]: UI_REQUEST.REQUEST_PASSPHRASE,\n [UI_RESPONSE.RECEIVE_PASSPHRASE_ON_DEVICE]: UI_REQUEST.REQUEST_PASSPHRASE_ON_DEVICE,\n [UI_RESPONSE.RECEIVE_SELECT_DEVICE]: UI_REQUEST.REQUEST_SELECT_DEVICE,\n [UI_RESPONSE.RECEIVE_DEVICE_CONNECT]: UI_REQUEST.REQUEST_DEVICE_CONNECT,\n [UI_RESPONSE.RECEIVE_DEVICE_PERMISSION]: UI_REQUEST.REQUEST_DEVICE_PERMISSION,\n [UI_RESPONSE.RECEIVE_BTC_HIGH_INDEX_CONFIRM]: UI_REQUEST.REQUEST_BTC_HIGH_INDEX_CONFIRM,\n [UI_RESPONSE.RECEIVE_INSTALL_APP]: UI_REQUEST.REQUEST_INSTALL_APP,\n // RECEIVE_QR_RESPONSE maps to QR_DISPLAY or QR_SCAN — resolved dynamically below.\n};\n\nexport const UI_REQUEST_PREEMPTED_TAG = 'UiRequestPreempted';\nexport const UI_REQUEST_CANCELLED_TAG = 'UiRequestCancelled';\nexport const UI_REQUEST_TIMEOUT_TAG = 'UiRequestTimeout';\n\ntype PendingEntry = {\n resolve: (payload: unknown) => void;\n reject: (error: Error) => void;\n timer: ReturnType<typeof setTimeout>;\n};\n\n/**\n * Per-type single-slot registry for adapter-level UI requests. A new `wait`\n * of the same type supersedes (rejects) the prior pending entry. With the\n * job queue running globally serially, cross-type collisions don't occur in\n * normal flow — same-type preemption is a defensive measure for callers\n * that fire the same request twice without waiting on the first.\n *\n * Unknown response types are dropped silently so the public `uiResponse`\n * entry never throws.\n */\nexport class UiRequestRegistry {\n private pending = new Map<string, PendingEntry>();\n\n wait<T = unknown>(requestType: string, options?: { timeoutMs?: number }): Promise<T> {\n const existing = this.pending.get(requestType);\n if (existing) {\n clearTimeout(existing.timer);\n this.pending.delete(requestType);\n existing.reject(\n Object.assign(new Error(`UI request '${requestType}' was superseded by a new request`), {\n _tag: UI_REQUEST_PREEMPTED_TAG,\n })\n );\n }\n\n const timeoutMs = options?.timeoutMs ?? UI_REQUEST_DEFAULT_TIMEOUT_MS;\n\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => {\n if (this.pending.get(requestType)?.timer === timer) {\n this.pending.delete(requestType);\n reject(\n Object.assign(new Error(`UI request '${requestType}' timed out after ${timeoutMs}ms`), {\n _tag: UI_REQUEST_TIMEOUT_TAG,\n })\n );\n }\n }, timeoutMs);\n\n this.pending.set(requestType, {\n resolve: resolve as (payload: unknown) => void,\n reject,\n timer,\n });\n });\n }\n\n resolve(responseType: string, payload: unknown): void {\n let requestType = RESPONSE_TO_REQUEST[responseType];\n if (responseType === UI_RESPONSE.RECEIVE_QR_RESPONSE) {\n if (this.pending.has(UI_REQUEST.REQUEST_QR_DISPLAY)) {\n requestType = UI_REQUEST.REQUEST_QR_DISPLAY;\n } else if (this.pending.has(UI_REQUEST.REQUEST_QR_SCAN)) {\n requestType = UI_REQUEST.REQUEST_QR_SCAN;\n }\n }\n if (!requestType) return;\n\n const entry = this.pending.get(requestType);\n if (!entry) return;\n\n clearTimeout(entry.timer);\n this.pending.delete(requestType);\n entry.resolve(payload);\n }\n\n cancel(requestType?: string): void {\n if (requestType) {\n const entry = this.pending.get(requestType);\n if (!entry) return;\n clearTimeout(entry.timer);\n this.pending.delete(requestType);\n entry.reject(\n Object.assign(new Error(`UI request '${requestType}' was cancelled`), {\n _tag: UI_REQUEST_CANCELLED_TAG,\n })\n );\n return;\n }\n\n for (const [type, entry] of this.pending) {\n clearTimeout(entry.timer);\n entry.reject(\n Object.assign(new Error(`UI request '${type}' was cancelled`), {\n _tag: UI_REQUEST_CANCELLED_TAG,\n })\n );\n }\n this.pending.clear();\n }\n\n reset(): void {\n this.cancel();\n }\n\n hasPending(requestType?: string): boolean {\n if (requestType) return this.pending.has(requestType);\n return this.pending.size > 0;\n }\n}\n","/**\n * Compare two semver strings (e.g. \"2.1.0\" vs \"2.3.1\").\n * Returns -1 if a < b, 0 if equal, 1 if a > b.\n */\nexport function compareSemver(a: string, b: string): number {\n const pa = a.split('.').map(Number);\n const pb = b.split('.').map(Number);\n for (let i = 0; i < 3; i++) {\n const va = pa[i] ?? 0;\n const vb = pb[i] ?? 0;\n if (va < vb) return -1;\n if (va > vb) return 1;\n }\n return 0;\n}\n","import { bytesToHex as nobleBytesToHex, hexToBytes as nobleHexToBytes } from '@noble/hashes/utils';\n\n/** Ensure hex string has 0x prefix */\nexport function ensure0x(hex: string): string {\n return hex.startsWith('0x') ? hex : `0x${hex}`;\n}\n\n/** Strip 0x prefix from hex string */\nexport function stripHex(hex: string): string {\n return hex.startsWith('0x') ? hex.slice(2) : hex;\n}\n\n/** Pad hex to 64 chars (32 bytes) with 0x prefix */\nexport function padHex64(hex: string): string {\n return `0x${stripHex(hex).padStart(64, '0')}`;\n}\n\n/**\n * Convert a hex string (with or without 0x prefix) to a Uint8Array.\n * Throws on invalid hex (non-hex characters, odd length).\n */\nexport function hexToBytes(hex: string): Uint8Array {\n return nobleHexToBytes(stripHex(hex));\n}\n\n/** Convert a Uint8Array to a hex string (no 0x prefix). */\nexport function bytesToHex(bytes: Uint8Array): string {\n return nobleBytesToHex(bytes);\n}\n","import { HardwareErrorCode } from '../types/errors';\n\n/**\n * Enrich a hardware error message with actionable recovery hints.\n * Shared across adapters (Ledger, Trezor, etc.).\n */\nexport function enrichErrorMessage(code: HardwareErrorCode, originalMessage: string): string {\n switch (code) {\n case HardwareErrorCode.PinInvalid:\n return `${originalMessage}. Please re-enter your PIN.`;\n case HardwareErrorCode.PinCancelled:\n return `${originalMessage}. PIN entry was cancelled.`;\n case HardwareErrorCode.DeviceBusy:\n return `${originalMessage}. The device is in use by another application. Close other wallet apps and try again.`;\n case HardwareErrorCode.DeviceDisconnected:\n return `${originalMessage}. Please reconnect the device and try again.`;\n case HardwareErrorCode.DeviceLocked:\n return `${originalMessage}. Please unlock your device and try again.`;\n case HardwareErrorCode.DeviceOneDeviceOnly:\n return `${originalMessage}. Disconnect the extra device and try again.`;\n case HardwareErrorCode.UserRejected:\n return `${originalMessage}. The request was rejected on the device.`;\n case HardwareErrorCode.WrongApp:\n return `${originalMessage}. Please open the correct app on your device.`;\n case HardwareErrorCode.AppNotInstalled:\n return `${originalMessage}. The required app is not installed on the device.`;\n case HardwareErrorCode.DeviceOutOfMemory:\n return `${originalMessage}. Not enough free space on the device. Please uninstall some apps and try again.`;\n case HardwareErrorCode.TransportNotAvailable:\n return `${originalMessage}. Ensure the device bridge/transport is available and running.`;\n case HardwareErrorCode.FirmwareTooOld:\n return `${originalMessage}. Please update your device firmware.`;\n case HardwareErrorCode.DeviceNotInitialized:\n return `${originalMessage}. The device may need to be set up first.`;\n case HardwareErrorCode.OperationTimeout:\n return `${originalMessage}. The operation timed out. Please try again.`;\n case HardwareErrorCode.EvmBlindSigningRequired:\n return 'Ledger: Blind signing not enabled in Ethereum app.';\n case HardwareErrorCode.EvmClearSignPluginMissing:\n return 'Ledger: Required plugin not installed (install via Ledger Live).';\n case HardwareErrorCode.EvmDataTooLarge:\n return 'Ledger: Transaction data too large for device memory.';\n case HardwareErrorCode.EvmTxTypeNotSupported:\n return 'Ledger: Transaction type not supported by current Ethereum app.';\n case HardwareErrorCode.AppTooOld:\n return 'Ledger: App out of date (update via Ledger Live).';\n case HardwareErrorCode.SolanaBlindSigningRequired:\n return 'Blind signing disabled in the Solana app.';\n case HardwareErrorCode.TronCustomContractRequired:\n return 'Custom Contracts setting disabled in the Tron app.';\n case HardwareErrorCode.TronDataSigningRequired:\n return 'Transactions Data setting disabled in the Tron app.';\n case HardwareErrorCode.TronSignByHashRequired:\n return 'Sign by Hash setting disabled in the Tron app.';\n case HardwareErrorCode.BtcWalletPolicyHmacMismatch:\n return 'Wallet policy not registered or HMAC mismatch.';\n case HardwareErrorCode.BtcUnexpectedState:\n return 'Signing aborted due to unexpected device state.';\n default:\n return originalMessage;\n }\n}\n","import type { Response } from '../types/response';\n\n/**\n * Generic batch call with progress reporting.\n * If any single call fails, returns the failure immediately.\n */\nexport async function batchCall<TParam, TResult>(\n params: TParam[],\n callFn: (p: TParam) => Promise<Response<TResult>>,\n onProgress?: (progress: { index: number; total: number }) => void\n): Promise<Response<TResult[]>> {\n const results: TResult[] = [];\n for (let i = 0; i < params.length; i++) {\n const result = await callFn(params[i]);\n if (!result.success) {\n return result;\n }\n results.push(result.payload);\n onProgress?.({ index: i, total: params.length });\n }\n return { success: true, payload: results };\n}\n"],"mappings":"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","names":["HardwareErrorCode","EConnectorInteraction","bytesToHex"]}
1
+ {"version":3,"sources":["../src/types/errors.ts","../src/types/response.ts","../src/types/fingerprint.ts","../src/events/device.ts","../src/events/ui-request.ts","../src/events/sdk.ts","../src/utils/DeviceJobQueue.ts","../src/types/connector.ts","../src/utils/TypedEventEmitter.ts","../src/utils/UiRequestRegistry.ts","../src/utils/semver.ts","../src/utils/hex.ts","../src/utils/errorMessages.ts","../src/utils/batchCall.ts"],"sourcesContent":["/**\n * HWK HardwareErrorCode — independent namespace from the legacy\n * `@onekeyfe/shared` HardwareErrorCode (which occupies 0-902).\n *\n * All HWK codes are 5-digit (>= 10000) so the two tables never collide\n * even if either side grows. Each sub-category gets a 100-slot block.\n *\n * 10000-10099 Generic / cross-cutting primitives\n * 10100-10199 Device state\n * 10200-10299 Firmware\n * 10300-10399 Transport + OS-level permission\n * 10400-10499 PIN / Passphrase\n * 10500-10599 App lifecycle (wrong app, not open, too old)\n * 10600-10999 RESERVED — future adapter-level categories\n *\n * 11000-11099 EVM APDU (reactive mapping)\n * 11100-11199 Solana APDU\n * 11200-11299 Tron APDU\n * 11300-11399 BTC APDU\n * 11400-11999 RESERVED — future chain APDU blocks (100 per chain)\n *\n * 12000-99999 RESERVED — future major categories\n */\nexport enum HardwareErrorCode {\n // --- 10000s Generic ---\n UnknownError = 10000,\n UserRejected = 10001,\n InvalidParams = 10002,\n OperationTimeout = 10003,\n MethodNotSupported = 10004,\n /** User dismissed in-app cancel UI. Distinct from UserRejected (on-device). */\n UserAborted = 10005,\n\n // --- 10100s Device state ---\n DeviceNotFound = 10100,\n DeviceDisconnected = 10101,\n DeviceBusy = 10102,\n DeviceLocked = 10103,\n DeviceNotInitialized = 10104,\n DeviceInBootloader = 10105,\n DeviceMismatch = 10106,\n /** Chain app wedged (e.g. Ledger BTC 0x6901). User must exit app on device. */\n DeviceAppStuck = 10107,\n /** Vendor (Ledger / Trezor) doesn't support the chain at all. */\n ChainNotSupported = 10108,\n /** Current operation supports only one connected device. */\n DeviceOneDeviceOnly = 10109,\n\n // --- 10200s Firmware ---\n FirmwareTooOld = 10200,\n FirmwareUpdateRequired = 10201,\n\n // --- 10300s Transport + permission ---\n TransportError = 10300,\n BridgeNotFound = 10301,\n TransportNotAvailable = 10302,\n /**\n * OS-level permission (Bluetooth / USB / etc.) — denied, blocked,\n * unavailable, or dismissed. Consumers surface a single \"please grant\n * permission\" toast and let the user retry manually.\n */\n DevicePermissionDenied = 10303,\n /**\n * BLE SMP pairing did not complete within the GATT bonding window.\n * GATT connected but the device didn't acknowledge SMP — typically\n * because the user didn't confirm the passkey on the device, or the\n * device went out of range mid-pairing. Distinct from OperationTimeout\n * (generic) and from DeviceLocked (Secure Element actually locked).\n */\n BlePairingTimeout = 10304,\n /** Remote network failure reaching a vendor's servers (HTTP/WS). Distinct from TransportError (local USB/BLE link). */\n NetworkError = 10305,\n\n // --- 10400s PIN / Passphrase ---\n PinInvalid = 10400,\n PinCancelled = 10401,\n PassphraseRejected = 10402,\n\n // --- 10500s App lifecycle ---\n /** Chain app NOT INSTALLED on device. User must install via Ledger Live. */\n AppNotInstalled = 10500,\n WrongApp = 10501,\n /** 0x911c Command code not supported — app predates current SDK. */\n AppTooOld = 10502,\n /** Not enough free storage for install/update; user must uninstall apps first. */\n DeviceOutOfMemory = 10503,\n\n // --- 11000s EVM (Ledger Ethereum App) APDU-specific ---\n /** 0x6a80 Invalid data — observed on blindSignTransactionFallback when the\n * user has not enabled Blind signing on the device. */\n EvmBlindSigningRequired = 11000,\n /** 0x6984 Plugin not installed */\n EvmClearSignPluginMissing = 11001,\n /** 0x6a84 Insufficient memory (typical on Nano S with large calldata) */\n EvmDataTooLarge = 11002,\n /** 0x6501 TransactionType not supported (app too old for EIP-1559 / blob / 7702) */\n EvmTxTypeNotSupported = 11003,\n\n // --- 11100s Solana ---\n /** 0x6808 Blind signing disabled for this instruction. */\n SolanaBlindSigningRequired = 11100,\n\n // --- 11200s Tron ---\n /** 0x6a8d Custom Contracts setting disabled (blocks TRC-20 etc.). */\n TronCustomContractRequired = 11200,\n /** 0x6a8b Transactions Data setting disabled. */\n TronDataSigningRequired = 11201,\n /** 0x6a8c Sign by Hash setting disabled (hash-signing fallback). */\n TronSignByHashRequired = 11202,\n\n // --- 11300s BTC ---\n /** 0xb008 Wallet policy HMAC mismatch or not registered. */\n BtcWalletPolicyHmacMismatch = 11300,\n /** 0xb007 Aborted due to unexpected state (malformed PSBT / missing UTXO). */\n BtcUnexpectedState = 11301,\n}\n\n/**\n * Device-level failures the SDK cannot self-recover from — affect the entire\n * batch (vs per-chain failures like AppNotInstalled / WrongApp which soft-\n * skip in onboarding). Combined with `accounts.length === 0`, signals\n * genuine orphan. Also reused as the batch-abort whitelist for HWK.\n * Single source of truth.\n *\n * UserRejected (device-side reject) is included: pressing reject is an\n * explicit \"I don't consent\" — continuing the batch to ask again on the\n * next chain is harassment, not helpful.\n */\nexport const ORPHAN_ELIGIBLE_ERROR_CODES: number[] = [\n HardwareErrorCode.UserAborted,\n HardwareErrorCode.UserRejected,\n HardwareErrorCode.DeviceNotFound,\n HardwareErrorCode.DeviceDisconnected,\n HardwareErrorCode.DeviceMismatch,\n HardwareErrorCode.DeviceAppStuck,\n HardwareErrorCode.DeviceOneDeviceOnly,\n HardwareErrorCode.TransportError,\n HardwareErrorCode.DevicePermissionDenied,\n HardwareErrorCode.BlePairingTimeout,\n];\n\n// ---------------------------------------------------------------------------\n// Standard throwable for HWK adapters\n// ---------------------------------------------------------------------------\n\nexport interface IHwkErrorPayload {\n code: HardwareErrorCode;\n message: string;\n appName?: string;\n _tag?: string;\n params?: Record<string, unknown>;\n}\n\nexport type HwkError = Error & {\n code: HardwareErrorCode;\n appName?: string;\n _tag?: string;\n params?: Record<string, unknown>;\n};\n\n/**\n * Canonical throwable for HWK adapters. Plain Error + canonical extra fields,\n * shape-compatible with `rehydrateConnectorError` so locally-thrown and\n * cross-boundary errors are indistinguishable to downstream classifiers\n * (`err.code` / `err._tag` / `err.appName`). Do NOT mutate caught errors\n * with `Object.assign` — construct a fresh one via this factory.\n */\nexport function createHwkError(payload: IHwkErrorPayload): HwkError {\n return Object.assign(new Error(payload.message), {\n code: payload.code,\n ...(payload._tag !== undefined && { _tag: payload._tag }),\n ...(payload.appName !== undefined && { appName: payload.appName }),\n ...(payload.params !== undefined && { params: payload.params }),\n });\n}\n","import type { HardwareErrorCode } from './errors';\n\nexport interface Success<T> {\n success: true;\n payload: T;\n}\n\nexport interface Failure {\n success: false;\n payload: {\n error: string;\n code: HardwareErrorCode;\n params?: Record<string, unknown>;\n };\n}\n\nexport type Response<T> = Success<T> | Failure;\n\nexport function success<T>(payload: T): Success<T> {\n return { success: true, payload };\n}\n\nexport function failure(\n code: HardwareErrorCode,\n error: string,\n params?: Record<string, unknown>\n): Failure {\n return {\n success: false,\n payload: { error, code, ...(params ? { params } : {}) },\n };\n}\n","/**\n * Chain fingerprint utilities for device identity verification.\n *\n * Ledger devices have ephemeral IDs that change every session.\n * To verify that the same seed/device is connected, we derive an address\n * at a fixed path (account 0, index 0) and hash it into a stable \"chain fingerprint\".\n */\nimport { sha256 } from '@noble/hashes/sha256';\nimport { bytesToHex, utf8ToBytes } from '@noble/hashes/utils';\n\n/**\n * Fixed derivation paths used to generate chain fingerprints.\n * Uses standard index 0 — Ledger firmware shows device confirmation for\n * non-standard paths (e.g., index=100), which would interrupt wallet creation.\n * The address is hashed into a 16-char fingerprint, not exposed directly.\n * - EVM: cointype 60 (Ledger ETH App only supports 60)\n * - BTC: cointype 1 (testnet)\n * - SOL: cointype 501, standard 3-level hardened\n */\nexport const CHAIN_FINGERPRINT_PATHS: Record<ChainForFingerprint, string> = {\n evm: \"m/44'/60'/0'/0/0\",\n // BTC: account-level path (3 levels), mainnet cointype 0.\n // Cointype 1 (testnet) is rejected by some Ledger BTC App configurations.\n btc: \"m/44'/0'/0'\",\n sol: \"m/44'/501'/0'\",\n tron: \"m/44'/195'/0'/0/0\",\n};\n\nexport type ChainForFingerprint = 'evm' | 'btc' | 'sol' | 'tron';\n\n/**\n * 16-char SHA-256 fingerprint for device-identity verification.\n * Callers must canonicalize input (e.g. EVM address → lowercase) —\n * encoding variations otherwise cause false DeviceMismatch.\n */\nexport function deriveDeviceFingerprint(value: string): string {\n return bytesToHex(sha256(utf8ToBytes(value))).slice(0, 16);\n}\n","export const DEVICE_EVENT = 'DEVICE_EVENT';\n\n/** Events originating from the hardware device. */\nexport const DEVICE = {\n CONNECT: 'device-connect',\n DISCONNECT: 'device-disconnect',\n CHANGED: 'device-changed',\n} as const;\n","import type { QrResponseData } from '../types/qr';\n\nexport const UI_EVENT = 'UI_EVENT';\n\nexport const UI_REQUEST = {\n REQUEST_PIN: 'ui-request-pin',\n REQUEST_PASSPHRASE: 'ui-request-passphrase',\n REQUEST_PASSPHRASE_ON_DEVICE: 'ui-request-passphrase-on-device',\n REQUEST_BUTTON: 'ui-request-button',\n REQUEST_QR_DISPLAY: 'ui-request-qr-display',\n REQUEST_QR_SCAN: 'ui-request-qr-scan',\n REQUEST_DEVICE_PERMISSION: 'ui-request-device-permission',\n REQUEST_SELECT_DEVICE: 'ui-request-select-device',\n REQUEST_DEVICE_CONNECT: 'ui-request-device-connect',\n // Ledger BTC App: account index >= 100 requires display=true. Adapter asks\n // the user once per session before promoting the call.\n REQUEST_BTC_HIGH_INDEX_CONFIRM: 'ui-request-btc-high-index-confirm',\n // Required app is not installed; with autoInstallApp on, ask the user\n // whether to install it before retrying the operation.\n REQUEST_INSTALL_APP: 'ui-request-install-app',\n CLOSE_UI_WINDOW: 'ui-close',\n DEVICE_PROGRESS: 'ui-device_progress',\n FIRMWARE_PROGRESS: 'ui-firmware-progress',\n FIRMWARE_TIP: 'ui-firmware-tip',\n} as const;\n\nexport const UI_RESPONSE = {\n RECEIVE_PIN: 'receive-pin',\n RECEIVE_PASSPHRASE: 'receive-passphrase',\n RECEIVE_PASSPHRASE_ON_DEVICE: 'receive-passphrase-on-device',\n RECEIVE_QR_RESPONSE: 'receive-qr-response',\n RECEIVE_SELECT_DEVICE: 'receive-select-device',\n RECEIVE_DEVICE_CONNECT: 'receive-device-connect',\n RECEIVE_DEVICE_PERMISSION: 'receive-device-permission',\n RECEIVE_BTC_HIGH_INDEX_CONFIRM: 'receive-btc-high-index-confirm',\n RECEIVE_INSTALL_APP: 'receive-install-app',\n CANCEL: 'cancel',\n} as const;\n\nexport type DevicePermissionDeniedReason =\n | 'bluetoothTurnedOff'\n | 'permissionDenied'\n | (string & Record<never, never>);\n\nexport type DevicePermissionResponse = {\n granted: boolean;\n reason?: DevicePermissionDeniedReason;\n message?: string;\n};\n\nexport type UiResponseEvent =\n | {\n type: typeof UI_RESPONSE.RECEIVE_PIN;\n payload: string;\n }\n | {\n type: typeof UI_RESPONSE.RECEIVE_PASSPHRASE;\n payload: {\n value: string;\n passphraseOnDevice?: boolean;\n save?: boolean;\n };\n }\n | {\n type: typeof UI_RESPONSE.RECEIVE_PASSPHRASE_ON_DEVICE;\n payload?: undefined;\n }\n | {\n type: typeof UI_RESPONSE.RECEIVE_QR_RESPONSE;\n payload: QrResponseData;\n }\n | {\n // sdkConnectId echoes one of the DeviceInfo.connectId values emitted in\n // the REQUEST_SELECT_DEVICE event's `devices` list. Scope is the current\n // search session; may be ephemeral (e.g. Ledger USB DMK UUID).\n type: typeof UI_RESPONSE.RECEIVE_SELECT_DEVICE;\n payload: { sdkConnectId: string };\n }\n | {\n type: typeof UI_RESPONSE.RECEIVE_DEVICE_CONNECT;\n payload: { confirmed: boolean };\n }\n | {\n type: typeof UI_RESPONSE.RECEIVE_DEVICE_PERMISSION;\n payload: DevicePermissionResponse;\n }\n | {\n type: typeof UI_RESPONSE.RECEIVE_BTC_HIGH_INDEX_CONFIRM;\n payload: { confirmed: boolean };\n }\n | {\n type: typeof UI_RESPONSE.RECEIVE_INSTALL_APP;\n payload: { confirmed: boolean };\n }\n | {\n type: typeof UI_RESPONSE.CANCEL;\n payload?: undefined;\n };\n","/** Events generated by SDK internal detection (not from hardware directly). */\nexport const SDK = {\n DEVICE_STUCK: 'device-stuck',\n DEVICE_UNRESPONSIVE: 'device-unresponsive',\n DEVICE_RECOVERED: 'device-recovered',\n DEVICE_INTERACTION: 'device-interaction',\n} as const;\n","/**\n * Pure FIFO job queue. Every enqueue chains onto the tail; jobs run one at\n * a time across all devices. The queue is intentionally passive — it does\n * NOT decide whether to interrupt or ask the user. Those are application-\n * layer concerns owned by the caller (e.g. a UI button handler that wants\n * to ask \"device is busy, interrupt current?\" before submitting). The\n * queue exposes inspection (`getActiveJob`) and explicit cancellation\n * (`cancelActive` / `cancelAll`) so callers can implement those policies\n * synchronously, without racing against in-flight enqueues.\n */\n\nexport interface JobOptions {\n label?: string;\n rejectIfBusy?: boolean;\n busyError?: Error;\n}\n\nexport interface ActiveJobInfo {\n deviceId: string;\n label?: string;\n startedAt: number;\n}\n\ninterface ActiveJob {\n deviceId: string;\n label?: string;\n abortController: AbortController;\n startedAt: number;\n}\n\nexport class DeviceJobQueue {\n private _tail: Promise<unknown> = Promise.resolve();\n\n private _active: ActiveJob | null = null;\n\n private readonly _jobs = new Map<object, { deviceId: string }>();\n\n /** Incremented on clear() so queued-but-not-yet-running jobs detect invalidation. */\n private _generation = 0;\n\n private readonly _generationCancelReasons = new Map<number, Error>();\n\n /**\n * Enqueue a job. Runs after every previously-enqueued job has settled.\n * `deviceId` is a label only — used by inspection / cancellation routing.\n */\n async enqueue<T>(\n deviceId: string,\n job: (signal: AbortSignal) => Promise<T>,\n options: JobOptions = {}\n ): Promise<T> {\n if (options.rejectIfBusy && this._jobs.size > 0) {\n throw options.busyError ?? new Error('Device is busy');\n }\n\n const ac = new AbortController();\n const gen = this._generation;\n const prev = this._tail;\n const jobToken = {};\n const activeJob: ActiveJob = {\n deviceId,\n label: options.label,\n abortController: ac,\n startedAt: Date.now(),\n };\n this._jobs.set(jobToken, { deviceId });\n\n const next = prev\n .catch(() => {})\n .then(async () => {\n if (this._generation !== gen) {\n throw (\n this._generationCancelReasons.get(gen) ?? new Error('Job cancelled: queue was cleared')\n );\n }\n this._active = activeJob;\n try {\n return await job(ac.signal);\n } finally {\n // Identity guard: a previous job's deferred finally must not\n // null out a successor's `_active`.\n if (this._active === activeJob) {\n this._active = null;\n }\n }\n })\n .finally(() => {\n this._jobs.delete(jobToken);\n });\n\n this._tail = next.catch(() => {});\n return next;\n }\n\n /** Cancel the active job. If `deviceId` is given, only cancels when it matches. */\n cancelActive(deviceId?: string): boolean {\n if (!this._active) return false;\n if (deviceId && this._active.deviceId !== deviceId) return false;\n this._active.abortController.abort(new Error('Manually cancelled'));\n return true;\n }\n\n /** Force cancel the active job. `reason` becomes signal.reason. */\n forceCancelActive(deviceId?: string, reason?: Error): boolean {\n if (!this._active) return false;\n if (deviceId && this._active.deviceId !== deviceId) return false;\n this._active.abortController.abort(reason ?? new Error('Force cancelled for recovery'));\n return true;\n }\n\n /** Cancel the active job (alias for callers that previously needed multi-device cancel). */\n cancelAllActive(reason?: Error): void {\n if (!this._active) return;\n this._active.abortController.abort(reason ?? new Error('Cancelled by cancelAllActive'));\n }\n\n /** Cancel the active job and invalidate queued jobs that have not started. */\n cancelActiveAndPending(deviceId?: string, reason?: Error): boolean {\n if (deviceId && this._active && this._active.deviceId !== deviceId) {\n return false;\n }\n this.clear(reason ?? new Error('Cancelled by cancelActiveAndPending'));\n return true;\n }\n\n /** Get info about the currently active job, or null if idle. */\n getActiveJob(deviceId?: string): ActiveJobInfo | null {\n if (!this._active) return null;\n if (deviceId && this._active.deviceId !== deviceId) return null;\n return {\n deviceId: this._active.deviceId,\n label: this._active.label,\n startedAt: this._active.startedAt,\n };\n }\n\n /** True if any job is currently running. */\n isBusy(): boolean {\n return this._jobs.size > 0;\n }\n\n clear(reason?: Error): void {\n const cancelledGeneration = this._generation;\n this._generation++;\n const cancelReason = reason ?? new Error('Job cancelled: queue was cleared');\n this._generationCancelReasons.set(cancelledGeneration, cancelReason);\n for (const generation of this._generationCancelReasons.keys()) {\n if (generation < this._generation - 10) {\n this._generationCancelReasons.delete(generation);\n }\n }\n if (this._active) {\n this._active.abortController.abort(cancelReason);\n }\n }\n}\n","import type { ConnectionType, DeviceCapabilities, DeviceInfo, VendorType } from './device';\nimport type { UiResponseEvent } from '../events/ui-request';\n\n// =====================================================================\n// Connector types — transport-level abstraction for device communication\n// =====================================================================\n\n/**\n * Minimal device info returned during discovery (searchDevices).\n * At scan time, full DeviceInfo fields like firmwareVersion are not yet available.\n */\nexport interface ConnectorDevice {\n connectId: string;\n deviceId: string;\n name: string;\n /** Machine model id (e.g. \"nanoX\"). */\n model?: string;\n /** Human-readable model name (e.g. \"Ledger Nano X\"). */\n modelName?: string;\n /** BLE signal strength (BLE only). */\n rssi?: number | null;\n /** BLE connectable flag (BLE only). */\n isConnectable?: boolean | null;\n /** USB serial number (USB only). */\n serialNumber?: string;\n\n /** Device capabilities — available from scan time */\n capabilities?: DeviceCapabilities;\n}\n\nexport interface ConnectorSession {\n sessionId: string;\n deviceInfo: DeviceInfo;\n}\n\n// =====================================================================\n// Connector call result — device errors travel as DATA, not exceptions\n//\n// `IConnector.call` never throws for device-level failures. It resolves a\n// discriminated result so the failure crosses any process boundary\n// (IHardwareBridge / extension offscreen↔SW) as plain `data`. This mirrors\n// the OneKey HD-SDK `IDeviceResponseResult` contract.\n//\n// WHY: when a thrown Error crosses the extension JsBridge it is run through\n// `toPlainError`, a fixed field whitelist that drops custom own-properties\n// (e.g. `appName`). Returning the failure as data keeps every field intact.\n//\n// Contract for `ConnectorSerializedError`: only `message` / `code` /\n// `errorCode` live at the top level; ALL other domain fields (`appName`,\n// `_tag`, `statusCode`, …) are nested under `params`.\n// =====================================================================\n\n/**\n * Vendor-agnostic bag of extra error fields. Known keys are documented for\n * discoverability; the index signature keeps it open so any connector can\n * carry vendor-specific data without losing it across the bridge.\n */\nexport interface ConnectorErrorParams {\n /** Vendor SDK error tag (e.g. Ledger DMK `_tag`). */\n _tag?: string;\n /** App involved, e.g. the Ledger app being opened/installed. */\n appName?: string;\n /** Transport / APDU status code (string or number depending on vendor). */\n statusCode?: unknown;\n /**\n * Shallow snapshot of a nested cause. A raw Error does not survive JSON\n * serialization (its `message`/`stack` are non-enumerable), so recovery\n * predicates that recurse into a cause get this plain-object copy instead.\n */\n originalError?: {\n message?: string;\n code?: number;\n errorCode?: string;\n statusCode?: unknown;\n _tag?: string;\n };\n [key: string]: unknown;\n}\n\nexport interface ConnectorSerializedError {\n message: string;\n code?: number;\n errorCode?: string;\n params?: ConnectorErrorParams;\n}\n\nexport type ConnectorCallResult =\n | { success: true; payload: unknown }\n | { success: false; error: ConnectorSerializedError };\n\nexport type ConnectorEventType = 'device-connect' | 'device-disconnect' | 'ui-request' | 'ui-event';\n\n/**\n * Interaction event types emitted via 'ui-event'.\n * These map to user-facing prompts (confirm on device, open app, etc.).\n */\nexport enum EConnectorInteraction {\n /** Adapter is actively searching for the device (no session yet) */\n Searching = 'searching',\n /** Device requires user to open a specific app */\n ConfirmOpenApp = 'confirm-open-app',\n /** Device requires user to unlock */\n UnlockDevice = 'unlock-device',\n /** Device needs user to confirm on device (sign, verify, etc.) */\n ConfirmOnDevice = 'confirm-on-device',\n /** Previous interaction completed — clear UI prompt */\n InteractionComplete = 'interaction-complete',\n /**\n * OS-level Ledger app install progress. `progress` is a 0..1 fraction\n * reported by DMK's InstallOrUpdateAppsDeviceAction. Emitted from inside\n * the connector so the progress callback ref never has to cross the\n * IHardwareBridge boundary.\n */\n AppInstallProgress = 'app-install-progress',\n}\n\n// Discriminated union: most variants only carry `sessionId`, but\n// AppInstallProgress also carries `appName` + `progress`. Searching has no\n// session yet so it carries an empty `sessionId`.\nexport type ConnectorUiEvent =\n | { type: EConnectorInteraction.Searching; payload: { sessionId: string } }\n | { type: EConnectorInteraction.ConfirmOpenApp; payload: { sessionId: string } }\n | { type: EConnectorInteraction.UnlockDevice; payload: { sessionId: string } }\n | { type: EConnectorInteraction.ConfirmOnDevice; payload: { sessionId: string } }\n | { type: EConnectorInteraction.InteractionComplete; payload: { sessionId: string } }\n | {\n type: EConnectorInteraction.AppInstallProgress;\n payload: { sessionId: string; appName: string; progress: number };\n };\n\nexport interface ConnectorEventMap {\n 'device-connect': { device: ConnectorDevice };\n 'device-disconnect': { connectId: string };\n 'ui-request': { type: string; payload?: unknown };\n 'ui-event': ConnectorUiEvent;\n}\n\nexport interface IConnector {\n /** Physical connection type this connector uses. Fixed at construction. */\n readonly connectionType: ConnectionType;\n\n searchDevices(): Promise<ConnectorDevice[]>;\n connect(deviceId?: string): Promise<ConnectorSession>;\n disconnect(sessionId: string): Promise<void>;\n // `call` resolves a discriminated result; device-level failures are returned\n // as data, never thrown (see ConnectorCallResult). Only `call` uses this\n // contract because it is the one method that carries rich, vendor-specific\n // domain errors across the IHardwareBridge boundary, where a thrown Error\n // would be stripped by the host bridge's error whitelist. The other methods\n // surface plain operational failures and still reject normally.\n call(sessionId: string, method: string, params: unknown): Promise<ConnectorCallResult>;\n cancel(sessionId: string): Promise<void>;\n\n /** Send a UI response (e.g. PIN, passphrase) to the device. */\n uiResponse(response: UiResponseEvent): void;\n\n on<K extends ConnectorEventType>(event: K, handler: (data: ConnectorEventMap[K]) => void): void;\n off<K extends ConnectorEventType>(event: K, handler: (data: ConnectorEventMap[K]) => void): void;\n\n reset(): void;\n}\n\n// =====================================================================\n// Hardware bridge — generic forwarding interface for cross-boundary IConnector\n//\n// The same shape works across any process / context boundary that needs to\n// expose a multi-vendor backend behind a single-vendor IConnector facade:\n// - Electron (renderer ↔ preload/main via contextBridge)\n// - Browser Extension (popup/content ↔ background/offscreen via chrome.runtime)\n// - React Native (JS ↔ native module via NativeModules)\n// - Web Worker / iframe (postMessage)\n//\n// Each method takes a `vendor` discriminator so a single bridge implementation\n// can multiplex across vendors (ledger, trezor, ...).\n// =====================================================================\n\nexport interface IHardwareBridge {\n searchDevices(params: { vendor: VendorType }): Promise<ConnectorDevice[]>;\n connect(params: { vendor: VendorType; deviceId?: string }): Promise<ConnectorSession>;\n disconnect(params: { vendor: VendorType; sessionId: string }): Promise<void>;\n call(params: {\n vendor: VendorType;\n sessionId: string;\n method: string;\n callParams: unknown;\n }): Promise<ConnectorCallResult>;\n cancel(params: { vendor: VendorType; sessionId: string }): Promise<void>;\n uiResponse(params: { vendor: VendorType; response: UiResponseEvent }): void;\n reset(params: { vendor: VendorType }): void;\n\n /** Register an event handler for connector events forwarded across the bridge. */\n onEvent(\n params: { vendor: VendorType },\n handler: (event: { type: ConnectorEventType; data: unknown }) => void\n ): void;\n\n /** Unregister a previously registered event handler. */\n offEvent(\n params: { vendor: VendorType },\n handler: (event: { type: ConnectorEventType; data: unknown }) => void\n ): void;\n}\n\n/**\n * Adapt an IHardwareBridge (multi-vendor backend) into a single-vendor IConnector.\n * Every IConnector method becomes a transparent forward to bridge.<method>({ vendor, ... }).\n * Events are forwarded via bridge.onEvent / offEvent.\n *\n * Use this anywhere the actual hardware lives behind a process / context boundary\n * (Electron main, extension background, native module, worker, iframe).\n */\nexport function createBridgedConnector(\n vendor: VendorType,\n connectionType: ConnectionType,\n bridge: IHardwareBridge\n): IConnector {\n // Keyed by (event, handler). A flat handler-only map would collide when the\n // same function is registered for multiple events — second .on() would\n // overwrite the first bridge handler reference, leaking it permanently.\n type UserHandler = (data: ConnectorEventMap[ConnectorEventType]) => void;\n type BridgeHandler = (event: { type: ConnectorEventType; data: unknown }) => void;\n const handlerMap = new Map<ConnectorEventType, Map<UserHandler, BridgeHandler>>();\n\n return {\n connectionType,\n searchDevices: () => bridge.searchDevices({ vendor }),\n connect: deviceId => bridge.connect({ vendor, deviceId }),\n disconnect: sessionId => bridge.disconnect({ vendor, sessionId }),\n call: (sessionId, method, callParams) => bridge.call({ vendor, sessionId, method, callParams }),\n cancel: sessionId => bridge.cancel({ vendor, sessionId }),\n uiResponse: response => bridge.uiResponse({ vendor, response }),\n on: (event, handler) => {\n const bridgeHandler: BridgeHandler = e => {\n if (e.type === event) {\n handler(e.data as ConnectorEventMap[typeof event]);\n }\n };\n let inner = handlerMap.get(event);\n if (!inner) {\n inner = new Map();\n handlerMap.set(event, inner);\n }\n inner.set(handler as UserHandler, bridgeHandler);\n bridge.onEvent({ vendor }, bridgeHandler);\n },\n off: (event, handler) => {\n const inner = handlerMap.get(event);\n const bridgeHandler = inner?.get(handler as UserHandler);\n if (!bridgeHandler || !inner) return;\n bridge.offEvent({ vendor }, bridgeHandler);\n inner.delete(handler as UserHandler);\n if (inner.size === 0) handlerMap.delete(event);\n },\n reset: () => bridge.reset({ vendor }),\n };\n}\n\n// =====================================================================\n// ConnectorCallResult error (de)serialization — the canonical, vendor-agnostic\n// helpers every IConnector implementation / adapter should use, so the\n// \"errors as data\" contract is identical across vendors.\n// =====================================================================\n\nconst SERIALIZED_ERROR_TOP_LEVEL_KEYS = new Set([\n 'message',\n 'code',\n 'errorCode',\n 'stack',\n 'params',\n]);\n\n/**\n * Flatten a thrown error into the cross-boundary-safe `ConnectorSerializedError`\n * shape. `message`/`code`/`errorCode` are lifted to the top level; every other\n * own-enumerable field is copied into `params` so NO domain data is lost when\n * the result crosses a host bridge (which may run thrown errors through a\n * field whitelist). A nested `originalError` is shallow-snapshotted because a\n * raw Error does not survive JSON serialization.\n */\nexport function serializeConnectorError(err: unknown): ConnectorSerializedError {\n if (!err || typeof err !== 'object') {\n return { message: typeof err === 'string' ? err : 'Unknown error' };\n }\n const e = err as Record<string, unknown>;\n const message = typeof e.message === 'string' ? e.message : 'Unknown error';\n const code = typeof e.code === 'number' ? e.code : undefined;\n const errorCode = e.errorCode != null ? String(e.errorCode) : undefined;\n\n const params: ConnectorErrorParams = {};\n // Flatten an existing `params` bag, then copy every other own field (so\n // vendor-specific keys like `_tag` / `statusCode` / `appName` / step context\n // are preserved without being named here).\n if (e.params && typeof e.params === 'object') {\n Object.assign(params, e.params as Record<string, unknown>);\n }\n for (const key of Object.keys(e)) {\n if (!SERIALIZED_ERROR_TOP_LEVEL_KEYS.has(key)) {\n params[key] = e[key];\n }\n }\n const orig = e.originalError;\n if (orig && typeof orig === 'object') {\n const o = orig as Record<string, unknown>;\n params.originalError = {\n message: typeof o.message === 'string' ? o.message : undefined,\n code: typeof o.code === 'number' ? o.code : undefined,\n errorCode: o.errorCode != null ? String(o.errorCode) : undefined,\n statusCode: o.statusCode,\n _tag: typeof o._tag === 'string' ? o._tag : undefined,\n };\n }\n\n // The result crosses host bridges via JSON.stringify. Drop any single field\n // that isn't JSON-safe (circular ref / non-serializable) so a pathological\n // error degrades to \"one field missing\" instead of crashing the transport.\n for (const key of Object.keys(params)) {\n try {\n JSON.stringify(params[key]);\n } catch {\n delete params[key];\n }\n }\n\n return {\n message,\n ...(code !== undefined ? { code } : {}),\n ...(errorCode !== undefined ? { errorCode } : {}),\n ...(Object.keys(params).length ? { params } : {}),\n };\n}\n\n/**\n * Inverse of `serializeConnectorError`: rebuild a flat Error instance, lifting\n * `params.*` back to own-properties so existing throw-based classifiers/recovery\n * logic (which read `err._tag` / `err.code` / `err.appName` / …) keep working\n * unchanged. The Result shape stays confined to the connector boundary.\n */\nexport function rehydrateConnectorError(error: ConnectorSerializedError): Error {\n const { message, code, errorCode, params } = error;\n return Object.assign(new Error(message), {\n ...(code !== undefined ? { code } : {}),\n ...(errorCode !== undefined ? { errorCode } : {}),\n ...(params ?? {}),\n });\n}\n","/**\n * Minimal typed event emitter using Map<string, Set<listener>>.\n * Each adapter uses this for device events (connect, disconnect, pin, etc.).\n *\n * TMap is a record mapping event name strings to their payload types.\n * Example:\n * type MyEvents = { 'connect': { id: string }; 'disconnect': { id: string } };\n * const emitter = new TypedEventEmitter<MyEvents>();\n * emitter.on('connect', (data) => { data.id }); // data is { id: string }\n *\n * For backward compatibility, TMap defaults to Record<string, any> so that\n * existing code using `new TypedEventEmitter<SomeUnionType>()` still compiles.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport class TypedEventEmitter<TMap extends Record<string, any> = Record<string, any>> {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private readonly _listeners = new Map<string, Set<(event: any) => void>>();\n\n on<K extends keyof TMap & string>(event: K, listener: (event: TMap[K]) => void): void;\n\n on(event: string, listener: (event: any) => void): void;\n\n on(event: string, listener: (event: any) => void): void {\n let set = this._listeners.get(event);\n if (!set) {\n set = new Set();\n this._listeners.set(event, set);\n }\n set.add(listener);\n }\n\n off<K extends keyof TMap & string>(event: K, listener: (event: TMap[K]) => void): void;\n\n off(event: string, listener: (event: any) => void): void;\n\n off(event: string, listener: (event: any) => void): void {\n const set = this._listeners.get(event);\n if (set) {\n set.delete(listener);\n if (set.size === 0) this._listeners.delete(event);\n }\n }\n\n emit<K extends keyof TMap & string>(event: K, data: TMap[K]): void;\n\n emit(event: string, data: unknown): void;\n\n emit(event: string, data: unknown): void {\n const set = this._listeners.get(event);\n if (set) {\n for (const listener of set) listener(data);\n }\n }\n\n removeAllListeners(): void {\n this._listeners.clear();\n }\n}\n","import { UI_REQUEST, UI_RESPONSE } from '../events/ui-request';\n\n/** 10 min — every UI request is human-in-the-loop; bias toward \"wait long\". */\nexport const UI_REQUEST_DEFAULT_TIMEOUT_MS = 600_000;\n\nconst RESPONSE_TO_REQUEST: Record<string, string> = {\n [UI_RESPONSE.RECEIVE_PIN]: UI_REQUEST.REQUEST_PIN,\n [UI_RESPONSE.RECEIVE_PASSPHRASE]: UI_REQUEST.REQUEST_PASSPHRASE,\n [UI_RESPONSE.RECEIVE_PASSPHRASE_ON_DEVICE]: UI_REQUEST.REQUEST_PASSPHRASE_ON_DEVICE,\n [UI_RESPONSE.RECEIVE_SELECT_DEVICE]: UI_REQUEST.REQUEST_SELECT_DEVICE,\n [UI_RESPONSE.RECEIVE_DEVICE_CONNECT]: UI_REQUEST.REQUEST_DEVICE_CONNECT,\n [UI_RESPONSE.RECEIVE_DEVICE_PERMISSION]: UI_REQUEST.REQUEST_DEVICE_PERMISSION,\n [UI_RESPONSE.RECEIVE_BTC_HIGH_INDEX_CONFIRM]: UI_REQUEST.REQUEST_BTC_HIGH_INDEX_CONFIRM,\n [UI_RESPONSE.RECEIVE_INSTALL_APP]: UI_REQUEST.REQUEST_INSTALL_APP,\n // RECEIVE_QR_RESPONSE maps to QR_DISPLAY or QR_SCAN — resolved dynamically below.\n};\n\nexport const UI_REQUEST_PREEMPTED_TAG = 'UiRequestPreempted';\nexport const UI_REQUEST_CANCELLED_TAG = 'UiRequestCancelled';\nexport const UI_REQUEST_TIMEOUT_TAG = 'UiRequestTimeout';\n\ntype PendingEntry = {\n resolve: (payload: unknown) => void;\n reject: (error: Error) => void;\n timer: ReturnType<typeof setTimeout>;\n};\n\n/**\n * Per-type single-slot registry for adapter-level UI requests. A new `wait`\n * of the same type supersedes (rejects) the prior pending entry. With the\n * job queue running globally serially, cross-type collisions don't occur in\n * normal flow — same-type preemption is a defensive measure for callers\n * that fire the same request twice without waiting on the first.\n *\n * Unknown response types are dropped silently so the public `uiResponse`\n * entry never throws.\n */\nexport class UiRequestRegistry {\n private pending = new Map<string, PendingEntry>();\n\n wait<T = unknown>(requestType: string, options?: { timeoutMs?: number }): Promise<T> {\n const existing = this.pending.get(requestType);\n if (existing) {\n clearTimeout(existing.timer);\n this.pending.delete(requestType);\n existing.reject(\n Object.assign(new Error(`UI request '${requestType}' was superseded by a new request`), {\n _tag: UI_REQUEST_PREEMPTED_TAG,\n })\n );\n }\n\n const timeoutMs = options?.timeoutMs ?? UI_REQUEST_DEFAULT_TIMEOUT_MS;\n\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => {\n if (this.pending.get(requestType)?.timer === timer) {\n this.pending.delete(requestType);\n reject(\n Object.assign(new Error(`UI request '${requestType}' timed out after ${timeoutMs}ms`), {\n _tag: UI_REQUEST_TIMEOUT_TAG,\n })\n );\n }\n }, timeoutMs);\n\n this.pending.set(requestType, {\n resolve: resolve as (payload: unknown) => void,\n reject,\n timer,\n });\n });\n }\n\n resolve(responseType: string, payload: unknown): void {\n let requestType = RESPONSE_TO_REQUEST[responseType];\n if (responseType === UI_RESPONSE.RECEIVE_QR_RESPONSE) {\n if (this.pending.has(UI_REQUEST.REQUEST_QR_DISPLAY)) {\n requestType = UI_REQUEST.REQUEST_QR_DISPLAY;\n } else if (this.pending.has(UI_REQUEST.REQUEST_QR_SCAN)) {\n requestType = UI_REQUEST.REQUEST_QR_SCAN;\n }\n }\n if (!requestType) return;\n\n const entry = this.pending.get(requestType);\n if (!entry) return;\n\n clearTimeout(entry.timer);\n this.pending.delete(requestType);\n entry.resolve(payload);\n }\n\n cancel(requestType?: string): void {\n if (requestType) {\n const entry = this.pending.get(requestType);\n if (!entry) return;\n clearTimeout(entry.timer);\n this.pending.delete(requestType);\n entry.reject(\n Object.assign(new Error(`UI request '${requestType}' was cancelled`), {\n _tag: UI_REQUEST_CANCELLED_TAG,\n })\n );\n return;\n }\n\n for (const [type, entry] of this.pending) {\n clearTimeout(entry.timer);\n entry.reject(\n Object.assign(new Error(`UI request '${type}' was cancelled`), {\n _tag: UI_REQUEST_CANCELLED_TAG,\n })\n );\n }\n this.pending.clear();\n }\n\n reset(): void {\n this.cancel();\n }\n\n hasPending(requestType?: string): boolean {\n if (requestType) return this.pending.has(requestType);\n return this.pending.size > 0;\n }\n}\n","/**\n * Compare two semver strings (e.g. \"2.1.0\" vs \"2.3.1\").\n * Returns -1 if a < b, 0 if equal, 1 if a > b.\n */\nexport function compareSemver(a: string, b: string): number {\n const pa = a.split('.').map(Number);\n const pb = b.split('.').map(Number);\n for (let i = 0; i < 3; i++) {\n const va = pa[i] ?? 0;\n const vb = pb[i] ?? 0;\n if (va < vb) return -1;\n if (va > vb) return 1;\n }\n return 0;\n}\n","import { bytesToHex as nobleBytesToHex, hexToBytes as nobleHexToBytes } from '@noble/hashes/utils';\n\n/** Ensure hex string has 0x prefix */\nexport function ensure0x(hex: string): string {\n return hex.startsWith('0x') ? hex : `0x${hex}`;\n}\n\n/** Strip 0x prefix from hex string */\nexport function stripHex(hex: string): string {\n return hex.startsWith('0x') ? hex.slice(2) : hex;\n}\n\n/** Pad hex to 64 chars (32 bytes) with 0x prefix */\nexport function padHex64(hex: string): string {\n return `0x${stripHex(hex).padStart(64, '0')}`;\n}\n\n/**\n * Convert a hex string (with or without 0x prefix) to a Uint8Array.\n * Throws on invalid hex (non-hex characters, odd length).\n */\nexport function hexToBytes(hex: string): Uint8Array {\n return nobleHexToBytes(stripHex(hex));\n}\n\n/** Convert a Uint8Array to a hex string (no 0x prefix). */\nexport function bytesToHex(bytes: Uint8Array): string {\n return nobleBytesToHex(bytes);\n}\n","import { HardwareErrorCode } from '../types/errors';\n\n/**\n * Enrich a hardware error message with actionable recovery hints.\n * Shared across adapters (Ledger, Trezor, etc.).\n */\nexport function enrichErrorMessage(code: HardwareErrorCode, originalMessage: string): string {\n switch (code) {\n case HardwareErrorCode.PinInvalid:\n return `${originalMessage}. Please re-enter your PIN.`;\n case HardwareErrorCode.PinCancelled:\n return `${originalMessage}. PIN entry was cancelled.`;\n case HardwareErrorCode.DeviceBusy:\n return `${originalMessage}. The device is in use by another application. Close other wallet apps and try again.`;\n case HardwareErrorCode.DeviceDisconnected:\n return `${originalMessage}. Please reconnect the device and try again.`;\n case HardwareErrorCode.DeviceLocked:\n return `${originalMessage}. Please unlock your device and try again.`;\n case HardwareErrorCode.DeviceOneDeviceOnly:\n return `${originalMessage}. Disconnect the extra device and try again.`;\n case HardwareErrorCode.UserRejected:\n return `${originalMessage}. The request was rejected on the device.`;\n case HardwareErrorCode.WrongApp:\n return `${originalMessage}. Please open the correct app on your device.`;\n case HardwareErrorCode.AppNotInstalled:\n return `${originalMessage}. The required app is not installed on the device.`;\n case HardwareErrorCode.DeviceOutOfMemory:\n return `${originalMessage}. Not enough free space on the device. Please uninstall some apps and try again.`;\n case HardwareErrorCode.TransportNotAvailable:\n return `${originalMessage}. Ensure the device bridge/transport is available and running.`;\n case HardwareErrorCode.NetworkError:\n return `${originalMessage}. Network error — check your internet connection and try again.`;\n case HardwareErrorCode.FirmwareTooOld:\n return `${originalMessage}. Please update your device firmware.`;\n case HardwareErrorCode.DeviceNotInitialized:\n return `${originalMessage}. The device may need to be set up first.`;\n case HardwareErrorCode.OperationTimeout:\n return `${originalMessage}. The operation timed out. Please try again.`;\n case HardwareErrorCode.EvmBlindSigningRequired:\n return 'Ledger: Blind signing not enabled in Ethereum app.';\n case HardwareErrorCode.EvmClearSignPluginMissing:\n return 'Ledger: Required plugin not installed (install via Ledger Live).';\n case HardwareErrorCode.EvmDataTooLarge:\n return 'Ledger: Transaction data too large for device memory.';\n case HardwareErrorCode.EvmTxTypeNotSupported:\n return 'Ledger: Transaction type not supported by current Ethereum app.';\n case HardwareErrorCode.AppTooOld:\n return 'Ledger: App out of date (update via Ledger Live).';\n case HardwareErrorCode.SolanaBlindSigningRequired:\n return 'Blind signing disabled in the Solana app.';\n case HardwareErrorCode.TronCustomContractRequired:\n return 'Custom Contracts setting disabled in the Tron app.';\n case HardwareErrorCode.TronDataSigningRequired:\n return 'Transactions Data setting disabled in the Tron app.';\n case HardwareErrorCode.TronSignByHashRequired:\n return 'Sign by Hash setting disabled in the Tron app.';\n case HardwareErrorCode.BtcWalletPolicyHmacMismatch:\n return 'Wallet policy not registered or HMAC mismatch.';\n case HardwareErrorCode.BtcUnexpectedState:\n return 'Signing aborted due to unexpected device state.';\n default:\n return originalMessage;\n }\n}\n","import type { Response } from '../types/response';\n\n/**\n * Generic batch call with progress reporting.\n * If any single call fails, returns the failure immediately.\n */\nexport async function batchCall<TParam, TResult>(\n params: TParam[],\n callFn: (p: TParam) => Promise<Response<TResult>>,\n onProgress?: (progress: { index: number; total: number }) => void\n): Promise<Response<TResult[]>> {\n const results: TResult[] = [];\n for (let i = 0; i < params.length; i++) {\n const result = await callFn(params[i]);\n if (!result.success) {\n return result;\n }\n results.push(result.payload);\n onProgress?.({ index: i, total: params.length });\n }\n return { success: true, payload: results };\n}\n"],"mappings":"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","names":["HardwareErrorCode","EConnectorInteraction","bytesToHex"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/hwk-adapter-core",
3
- "version": "1.2.0-alpha.1",
3
+ "version": "1.2.0-alpha.2",
4
4
  "description": "Shared types and utilities for OneKey hardware wallet kit",
5
5
  "author": "OneKey",
6
6
  "license": "MIT",
@@ -50,5 +50,5 @@
50
50
  "tsup": "^8.0.0",
51
51
  "typescript": "^5.4.0"
52
52
  },
53
- "gitHead": "4f4aae3a47be7bd54b4db4a10c400056784e01bd"
53
+ "gitHead": "6c183b7f7027f4b4d3db4f427f6360351a6c6680"
54
54
  }