@onekeyfe/hwk-adapter-core 1.1.27-alpha.35 → 1.1.27-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +60 -5
- package/dist/index.d.ts +60 -5
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +7 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -40,6 +40,8 @@ declare enum HardwareErrorCode {
|
|
|
40
40
|
DeviceAppStuck = 10107,
|
|
41
41
|
/** Vendor (Ledger / Trezor) doesn't support the chain at all. */
|
|
42
42
|
ChainNotSupported = 10108,
|
|
43
|
+
/** Current operation supports only one connected device. */
|
|
44
|
+
DeviceOneDeviceOnly = 10109,
|
|
43
45
|
FirmwareTooOld = 10200,
|
|
44
46
|
FirmwareUpdateRequired = 10201,
|
|
45
47
|
TransportError = 10300,
|
|
@@ -67,6 +69,8 @@ declare enum HardwareErrorCode {
|
|
|
67
69
|
WrongApp = 10501,
|
|
68
70
|
/** 0x911c Command code not supported — app predates current SDK. */
|
|
69
71
|
AppTooOld = 10502,
|
|
72
|
+
/** Not enough free storage for install/update; user must uninstall apps first. */
|
|
73
|
+
DeviceOutOfMemory = 10503,
|
|
70
74
|
/** 0x6a80 Invalid data — observed on blindSignTransactionFallback when the
|
|
71
75
|
* user has not enabled Blind signing on the device. */
|
|
72
76
|
EvmBlindSigningRequired = 11000,
|
|
@@ -141,13 +145,22 @@ interface DeviceCapabilities {
|
|
|
141
145
|
}
|
|
142
146
|
interface DeviceInfo {
|
|
143
147
|
vendor: VendorType;
|
|
148
|
+
/** Machine model id (e.g. "nanoX"). */
|
|
144
149
|
model: string;
|
|
150
|
+
/** Human-readable model name (e.g. "Ledger Nano X"). */
|
|
151
|
+
modelName?: string;
|
|
145
152
|
firmwareVersion: string;
|
|
146
153
|
deviceId: string;
|
|
147
154
|
connectId: string;
|
|
148
155
|
label?: string;
|
|
149
156
|
connectionType: ConnectionType;
|
|
150
157
|
battery?: number;
|
|
158
|
+
/** BLE signal strength (BLE only). */
|
|
159
|
+
rssi?: number | null;
|
|
160
|
+
/** BLE connectable flag (BLE only). */
|
|
161
|
+
isConnectable?: boolean | null;
|
|
162
|
+
/** USB serial number (USB only). */
|
|
163
|
+
serialNumber?: string;
|
|
151
164
|
/** Device capabilities — varies by vendor, model, and connection type */
|
|
152
165
|
capabilities?: DeviceCapabilities;
|
|
153
166
|
}
|
|
@@ -547,7 +560,16 @@ interface ConnectorDevice {
|
|
|
547
560
|
connectId: string;
|
|
548
561
|
deviceId: string;
|
|
549
562
|
name: string;
|
|
563
|
+
/** Machine model id (e.g. "nanoX"). */
|
|
550
564
|
model?: string;
|
|
565
|
+
/** Human-readable model name (e.g. "Ledger Nano X"). */
|
|
566
|
+
modelName?: string;
|
|
567
|
+
/** BLE signal strength (BLE only). */
|
|
568
|
+
rssi?: number | null;
|
|
569
|
+
/** BLE connectable flag (BLE only). */
|
|
570
|
+
isConnectable?: boolean | null;
|
|
571
|
+
/** USB serial number (USB only). */
|
|
572
|
+
serialNumber?: string;
|
|
551
573
|
/** Device capabilities — available from scan time */
|
|
552
574
|
capabilities?: DeviceCapabilities;
|
|
553
575
|
}
|
|
@@ -555,7 +577,7 @@ interface ConnectorSession {
|
|
|
555
577
|
sessionId: string;
|
|
556
578
|
deviceInfo: DeviceInfo;
|
|
557
579
|
}
|
|
558
|
-
type ConnectorEventType = 'device-connect' | 'device-disconnect' | 'ui-request' | 'ui-event';
|
|
580
|
+
type ConnectorEventType = 'device-connect' | 'device-disconnect' | 'ui-request' | 'ui-event' | 'app-install-progress';
|
|
559
581
|
/**
|
|
560
582
|
* Interaction event types emitted via 'ui-event'.
|
|
561
583
|
* These map to user-facing prompts (confirm on device, open app, etc.).
|
|
@@ -610,6 +632,11 @@ interface ConnectorEventMap {
|
|
|
610
632
|
payload?: unknown;
|
|
611
633
|
};
|
|
612
634
|
'ui-event': ConnectorUiEvent;
|
|
635
|
+
'app-install-progress': {
|
|
636
|
+
sessionId: string;
|
|
637
|
+
appName: string;
|
|
638
|
+
progress: number;
|
|
639
|
+
};
|
|
613
640
|
}
|
|
614
641
|
interface IConnector {
|
|
615
642
|
/** Physical connection type this connector uses. Fixed at construction. */
|
|
@@ -797,6 +824,14 @@ type DeviceEventListener = (event: HardwareEvent) => void;
|
|
|
797
824
|
*/
|
|
798
825
|
interface HardwareEventMap {
|
|
799
826
|
'ui-event': ConnectorUiEvent;
|
|
827
|
+
'app-install-progress': {
|
|
828
|
+
type: 'app-install-progress';
|
|
829
|
+
payload: {
|
|
830
|
+
connectId: string;
|
|
831
|
+
appName: string;
|
|
832
|
+
progress: number;
|
|
833
|
+
};
|
|
834
|
+
};
|
|
800
835
|
[DEVICE.CONNECT]: {
|
|
801
836
|
type: typeof DEVICE.CONNECT;
|
|
802
837
|
payload: DeviceInfo;
|
|
@@ -916,7 +951,7 @@ interface IHardwareWallet<TConfig = unknown> extends IEvmMethods, IBtcMethods, I
|
|
|
916
951
|
dispose(): Promise<void>;
|
|
917
952
|
getAvailableTransports(): TransportType[];
|
|
918
953
|
switchTransport(type: TransportType): Promise<void>;
|
|
919
|
-
searchDevices(): Promise<DeviceInfo[]>;
|
|
954
|
+
searchDevices(options?: SearchDevicesOptions): Promise<DeviceInfo[]>;
|
|
920
955
|
connectDevice(connectId: string): Promise<Response<string>>;
|
|
921
956
|
disconnectDevice(connectId: string): Promise<void>;
|
|
922
957
|
getDeviceInfo(connectId: string, deviceId: string): Promise<Response<DeviceInfo>>;
|
|
@@ -940,6 +975,16 @@ interface IHardwareWallet<TConfig = unknown> extends IEvmMethods, IBtcMethods, I
|
|
|
940
975
|
off<K extends keyof HardwareEventMap>(event: K, listener: (event: HardwareEventMap[K]) => void): void;
|
|
941
976
|
off(event: string, listener: DeviceEventListener): void;
|
|
942
977
|
}
|
|
978
|
+
interface SearchDevicesOptions {
|
|
979
|
+
/**
|
|
980
|
+
* Clear cached adapter sessions before scanning.
|
|
981
|
+
*
|
|
982
|
+
* Use this for an explicit "search/add another device" flow on transports
|
|
983
|
+
* whose connectId is not stable, such as Ledger WebHID. Normal refresh scans
|
|
984
|
+
* should leave this false so an active session can still be reused.
|
|
985
|
+
*/
|
|
986
|
+
resetSession?: boolean;
|
|
987
|
+
}
|
|
943
988
|
|
|
944
989
|
/**
|
|
945
990
|
* Low-level device descriptor from Transport layer.
|
|
@@ -952,11 +997,13 @@ interface DeviceDescriptor {
|
|
|
952
997
|
product?: number;
|
|
953
998
|
/** USB vendor ID */
|
|
954
999
|
vendor?: number;
|
|
955
|
-
/** Device type/model identifier */
|
|
1000
|
+
/** Device type/model identifier (e.g. "nanoX"). */
|
|
956
1001
|
type?: string;
|
|
1002
|
+
/** Human-readable model name (e.g. "Ledger Nano X"). */
|
|
1003
|
+
modelName?: string;
|
|
957
1004
|
/** Human-readable display name from the transport layer. */
|
|
958
1005
|
name?: string;
|
|
959
|
-
/**
|
|
1006
|
+
/** Raw Ledger BLE advertisement name from RN BLE `Device.name`, when available. */
|
|
960
1007
|
bleName?: string;
|
|
961
1008
|
/** User-visible Ledger BLE local name from the raw RN BLE `Device.localName` field. */
|
|
962
1009
|
localName?: string;
|
|
@@ -964,6 +1011,14 @@ interface DeviceDescriptor {
|
|
|
964
1011
|
transport?: string;
|
|
965
1012
|
/** BLE RSSI when provided by the transport scanner. */
|
|
966
1013
|
rssi?: number | null;
|
|
1014
|
+
/** BLE advertised service UUIDs, when provided by the scanner. */
|
|
1015
|
+
serviceUUIDs?: string[] | null;
|
|
1016
|
+
/** BLE connectable flag, when provided by the scanner. */
|
|
1017
|
+
isConnectable?: boolean | null;
|
|
1018
|
+
/** USB product name, when provided by the transport. */
|
|
1019
|
+
productName?: string;
|
|
1020
|
+
/** USB serial number, when provided by the transport. */
|
|
1021
|
+
serialNumber?: string;
|
|
967
1022
|
}
|
|
968
1023
|
interface DeviceConnectEvent {
|
|
969
1024
|
type: 'device-connected';
|
|
@@ -1107,4 +1162,4 @@ declare function batchCall<TParam, TResult>(params: TParam[], callFn: (p: TParam
|
|
|
1107
1162
|
total: number;
|
|
1108
1163
|
}) => void): Promise<Response<TResult[]>>;
|
|
1109
1164
|
|
|
1110
|
-
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 ConnectorDevice, type ConnectorEventMap, type ConnectorEventType, 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 IBtcMethods, 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 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, stripHex, success };
|
|
1165
|
+
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 ConnectorDevice, type ConnectorEventMap, type ConnectorEventType, 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 IBtcMethods, 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, stripHex, success };
|
package/dist/index.d.ts
CHANGED
|
@@ -40,6 +40,8 @@ declare enum HardwareErrorCode {
|
|
|
40
40
|
DeviceAppStuck = 10107,
|
|
41
41
|
/** Vendor (Ledger / Trezor) doesn't support the chain at all. */
|
|
42
42
|
ChainNotSupported = 10108,
|
|
43
|
+
/** Current operation supports only one connected device. */
|
|
44
|
+
DeviceOneDeviceOnly = 10109,
|
|
43
45
|
FirmwareTooOld = 10200,
|
|
44
46
|
FirmwareUpdateRequired = 10201,
|
|
45
47
|
TransportError = 10300,
|
|
@@ -67,6 +69,8 @@ declare enum HardwareErrorCode {
|
|
|
67
69
|
WrongApp = 10501,
|
|
68
70
|
/** 0x911c Command code not supported — app predates current SDK. */
|
|
69
71
|
AppTooOld = 10502,
|
|
72
|
+
/** Not enough free storage for install/update; user must uninstall apps first. */
|
|
73
|
+
DeviceOutOfMemory = 10503,
|
|
70
74
|
/** 0x6a80 Invalid data — observed on blindSignTransactionFallback when the
|
|
71
75
|
* user has not enabled Blind signing on the device. */
|
|
72
76
|
EvmBlindSigningRequired = 11000,
|
|
@@ -141,13 +145,22 @@ interface DeviceCapabilities {
|
|
|
141
145
|
}
|
|
142
146
|
interface DeviceInfo {
|
|
143
147
|
vendor: VendorType;
|
|
148
|
+
/** Machine model id (e.g. "nanoX"). */
|
|
144
149
|
model: string;
|
|
150
|
+
/** Human-readable model name (e.g. "Ledger Nano X"). */
|
|
151
|
+
modelName?: string;
|
|
145
152
|
firmwareVersion: string;
|
|
146
153
|
deviceId: string;
|
|
147
154
|
connectId: string;
|
|
148
155
|
label?: string;
|
|
149
156
|
connectionType: ConnectionType;
|
|
150
157
|
battery?: number;
|
|
158
|
+
/** BLE signal strength (BLE only). */
|
|
159
|
+
rssi?: number | null;
|
|
160
|
+
/** BLE connectable flag (BLE only). */
|
|
161
|
+
isConnectable?: boolean | null;
|
|
162
|
+
/** USB serial number (USB only). */
|
|
163
|
+
serialNumber?: string;
|
|
151
164
|
/** Device capabilities — varies by vendor, model, and connection type */
|
|
152
165
|
capabilities?: DeviceCapabilities;
|
|
153
166
|
}
|
|
@@ -547,7 +560,16 @@ interface ConnectorDevice {
|
|
|
547
560
|
connectId: string;
|
|
548
561
|
deviceId: string;
|
|
549
562
|
name: string;
|
|
563
|
+
/** Machine model id (e.g. "nanoX"). */
|
|
550
564
|
model?: string;
|
|
565
|
+
/** Human-readable model name (e.g. "Ledger Nano X"). */
|
|
566
|
+
modelName?: string;
|
|
567
|
+
/** BLE signal strength (BLE only). */
|
|
568
|
+
rssi?: number | null;
|
|
569
|
+
/** BLE connectable flag (BLE only). */
|
|
570
|
+
isConnectable?: boolean | null;
|
|
571
|
+
/** USB serial number (USB only). */
|
|
572
|
+
serialNumber?: string;
|
|
551
573
|
/** Device capabilities — available from scan time */
|
|
552
574
|
capabilities?: DeviceCapabilities;
|
|
553
575
|
}
|
|
@@ -555,7 +577,7 @@ interface ConnectorSession {
|
|
|
555
577
|
sessionId: string;
|
|
556
578
|
deviceInfo: DeviceInfo;
|
|
557
579
|
}
|
|
558
|
-
type ConnectorEventType = 'device-connect' | 'device-disconnect' | 'ui-request' | 'ui-event';
|
|
580
|
+
type ConnectorEventType = 'device-connect' | 'device-disconnect' | 'ui-request' | 'ui-event' | 'app-install-progress';
|
|
559
581
|
/**
|
|
560
582
|
* Interaction event types emitted via 'ui-event'.
|
|
561
583
|
* These map to user-facing prompts (confirm on device, open app, etc.).
|
|
@@ -610,6 +632,11 @@ interface ConnectorEventMap {
|
|
|
610
632
|
payload?: unknown;
|
|
611
633
|
};
|
|
612
634
|
'ui-event': ConnectorUiEvent;
|
|
635
|
+
'app-install-progress': {
|
|
636
|
+
sessionId: string;
|
|
637
|
+
appName: string;
|
|
638
|
+
progress: number;
|
|
639
|
+
};
|
|
613
640
|
}
|
|
614
641
|
interface IConnector {
|
|
615
642
|
/** Physical connection type this connector uses. Fixed at construction. */
|
|
@@ -797,6 +824,14 @@ type DeviceEventListener = (event: HardwareEvent) => void;
|
|
|
797
824
|
*/
|
|
798
825
|
interface HardwareEventMap {
|
|
799
826
|
'ui-event': ConnectorUiEvent;
|
|
827
|
+
'app-install-progress': {
|
|
828
|
+
type: 'app-install-progress';
|
|
829
|
+
payload: {
|
|
830
|
+
connectId: string;
|
|
831
|
+
appName: string;
|
|
832
|
+
progress: number;
|
|
833
|
+
};
|
|
834
|
+
};
|
|
800
835
|
[DEVICE.CONNECT]: {
|
|
801
836
|
type: typeof DEVICE.CONNECT;
|
|
802
837
|
payload: DeviceInfo;
|
|
@@ -916,7 +951,7 @@ interface IHardwareWallet<TConfig = unknown> extends IEvmMethods, IBtcMethods, I
|
|
|
916
951
|
dispose(): Promise<void>;
|
|
917
952
|
getAvailableTransports(): TransportType[];
|
|
918
953
|
switchTransport(type: TransportType): Promise<void>;
|
|
919
|
-
searchDevices(): Promise<DeviceInfo[]>;
|
|
954
|
+
searchDevices(options?: SearchDevicesOptions): Promise<DeviceInfo[]>;
|
|
920
955
|
connectDevice(connectId: string): Promise<Response<string>>;
|
|
921
956
|
disconnectDevice(connectId: string): Promise<void>;
|
|
922
957
|
getDeviceInfo(connectId: string, deviceId: string): Promise<Response<DeviceInfo>>;
|
|
@@ -940,6 +975,16 @@ interface IHardwareWallet<TConfig = unknown> extends IEvmMethods, IBtcMethods, I
|
|
|
940
975
|
off<K extends keyof HardwareEventMap>(event: K, listener: (event: HardwareEventMap[K]) => void): void;
|
|
941
976
|
off(event: string, listener: DeviceEventListener): void;
|
|
942
977
|
}
|
|
978
|
+
interface SearchDevicesOptions {
|
|
979
|
+
/**
|
|
980
|
+
* Clear cached adapter sessions before scanning.
|
|
981
|
+
*
|
|
982
|
+
* Use this for an explicit "search/add another device" flow on transports
|
|
983
|
+
* whose connectId is not stable, such as Ledger WebHID. Normal refresh scans
|
|
984
|
+
* should leave this false so an active session can still be reused.
|
|
985
|
+
*/
|
|
986
|
+
resetSession?: boolean;
|
|
987
|
+
}
|
|
943
988
|
|
|
944
989
|
/**
|
|
945
990
|
* Low-level device descriptor from Transport layer.
|
|
@@ -952,11 +997,13 @@ interface DeviceDescriptor {
|
|
|
952
997
|
product?: number;
|
|
953
998
|
/** USB vendor ID */
|
|
954
999
|
vendor?: number;
|
|
955
|
-
/** Device type/model identifier */
|
|
1000
|
+
/** Device type/model identifier (e.g. "nanoX"). */
|
|
956
1001
|
type?: string;
|
|
1002
|
+
/** Human-readable model name (e.g. "Ledger Nano X"). */
|
|
1003
|
+
modelName?: string;
|
|
957
1004
|
/** Human-readable display name from the transport layer. */
|
|
958
1005
|
name?: string;
|
|
959
|
-
/**
|
|
1006
|
+
/** Raw Ledger BLE advertisement name from RN BLE `Device.name`, when available. */
|
|
960
1007
|
bleName?: string;
|
|
961
1008
|
/** User-visible Ledger BLE local name from the raw RN BLE `Device.localName` field. */
|
|
962
1009
|
localName?: string;
|
|
@@ -964,6 +1011,14 @@ interface DeviceDescriptor {
|
|
|
964
1011
|
transport?: string;
|
|
965
1012
|
/** BLE RSSI when provided by the transport scanner. */
|
|
966
1013
|
rssi?: number | null;
|
|
1014
|
+
/** BLE advertised service UUIDs, when provided by the scanner. */
|
|
1015
|
+
serviceUUIDs?: string[] | null;
|
|
1016
|
+
/** BLE connectable flag, when provided by the scanner. */
|
|
1017
|
+
isConnectable?: boolean | null;
|
|
1018
|
+
/** USB product name, when provided by the transport. */
|
|
1019
|
+
productName?: string;
|
|
1020
|
+
/** USB serial number, when provided by the transport. */
|
|
1021
|
+
serialNumber?: string;
|
|
967
1022
|
}
|
|
968
1023
|
interface DeviceConnectEvent {
|
|
969
1024
|
type: 'device-connected';
|
|
@@ -1107,4 +1162,4 @@ declare function batchCall<TParam, TResult>(params: TParam[], callFn: (p: TParam
|
|
|
1107
1162
|
total: number;
|
|
1108
1163
|
}) => void): Promise<Response<TResult[]>>;
|
|
1109
1164
|
|
|
1110
|
-
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 ConnectorDevice, type ConnectorEventMap, type ConnectorEventType, 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 IBtcMethods, 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 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, stripHex, success };
|
|
1165
|
+
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 ConnectorDevice, type ConnectorEventMap, type ConnectorEventType, 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 IBtcMethods, 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, stripHex, success };
|
package/dist/index.js
CHANGED
|
@@ -69,6 +69,7 @@ var HardwareErrorCode = /* @__PURE__ */ ((HardwareErrorCode2) => {
|
|
|
69
69
|
HardwareErrorCode2[HardwareErrorCode2["DeviceMismatch"] = 10106] = "DeviceMismatch";
|
|
70
70
|
HardwareErrorCode2[HardwareErrorCode2["DeviceAppStuck"] = 10107] = "DeviceAppStuck";
|
|
71
71
|
HardwareErrorCode2[HardwareErrorCode2["ChainNotSupported"] = 10108] = "ChainNotSupported";
|
|
72
|
+
HardwareErrorCode2[HardwareErrorCode2["DeviceOneDeviceOnly"] = 10109] = "DeviceOneDeviceOnly";
|
|
72
73
|
HardwareErrorCode2[HardwareErrorCode2["FirmwareTooOld"] = 10200] = "FirmwareTooOld";
|
|
73
74
|
HardwareErrorCode2[HardwareErrorCode2["FirmwareUpdateRequired"] = 10201] = "FirmwareUpdateRequired";
|
|
74
75
|
HardwareErrorCode2[HardwareErrorCode2["TransportError"] = 10300] = "TransportError";
|
|
@@ -82,6 +83,7 @@ var HardwareErrorCode = /* @__PURE__ */ ((HardwareErrorCode2) => {
|
|
|
82
83
|
HardwareErrorCode2[HardwareErrorCode2["AppNotInstalled"] = 10500] = "AppNotInstalled";
|
|
83
84
|
HardwareErrorCode2[HardwareErrorCode2["WrongApp"] = 10501] = "WrongApp";
|
|
84
85
|
HardwareErrorCode2[HardwareErrorCode2["AppTooOld"] = 10502] = "AppTooOld";
|
|
86
|
+
HardwareErrorCode2[HardwareErrorCode2["DeviceOutOfMemory"] = 10503] = "DeviceOutOfMemory";
|
|
85
87
|
HardwareErrorCode2[HardwareErrorCode2["EvmBlindSigningRequired"] = 11e3] = "EvmBlindSigningRequired";
|
|
86
88
|
HardwareErrorCode2[HardwareErrorCode2["EvmClearSignPluginMissing"] = 11001] = "EvmClearSignPluginMissing";
|
|
87
89
|
HardwareErrorCode2[HardwareErrorCode2["EvmDataTooLarge"] = 11002] = "EvmDataTooLarge";
|
|
@@ -101,6 +103,7 @@ var ORPHAN_ELIGIBLE_ERROR_CODES = [
|
|
|
101
103
|
10101 /* DeviceDisconnected */,
|
|
102
104
|
10106 /* DeviceMismatch */,
|
|
103
105
|
10107 /* DeviceAppStuck */,
|
|
106
|
+
10109 /* DeviceOneDeviceOnly */,
|
|
104
107
|
10300 /* TransportError */,
|
|
105
108
|
10303 /* DevicePermissionDenied */,
|
|
106
109
|
10304 /* BlePairingTimeout */
|
|
@@ -504,12 +507,16 @@ function enrichErrorMessage(code, originalMessage) {
|
|
|
504
507
|
return `${originalMessage}. Please reconnect the device and try again.`;
|
|
505
508
|
case 10103 /* DeviceLocked */:
|
|
506
509
|
return `${originalMessage}. Please unlock your device and try again.`;
|
|
510
|
+
case 10109 /* DeviceOneDeviceOnly */:
|
|
511
|
+
return `${originalMessage}. Disconnect the extra device and try again.`;
|
|
507
512
|
case 10001 /* UserRejected */:
|
|
508
513
|
return `${originalMessage}. The request was rejected on the device.`;
|
|
509
514
|
case 10501 /* WrongApp */:
|
|
510
515
|
return `${originalMessage}. Please open the correct app on your device.`;
|
|
511
516
|
case 10500 /* AppNotInstalled */:
|
|
512
517
|
return `${originalMessage}. The required app is not installed on the device.`;
|
|
518
|
+
case 10503 /* DeviceOutOfMemory */:
|
|
519
|
+
return `${originalMessage}. Not enough free space on the device. Please uninstall some apps and try again.`;
|
|
513
520
|
case 10302 /* TransportNotAvailable */:
|
|
514
521
|
return `${originalMessage}. Ensure the device bridge/transport is available and running.`;
|
|
515
522
|
case 10200 /* FirmwareTooOld */:
|
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 PassphraseResponse,\n ChainCapability,\n DeviceEvent,\n UiRequestEvent,\n SdkEvent,\n HardwareEvent,\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 IConnector,\n IHardwareBridge,\n} from './types/connector';\nexport { createBridgedConnector, EConnectorInteraction } 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\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\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.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 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 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.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 model?: 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\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\n// All variants share the same payload shape so that emit sites where the\n// `type` is a broad `EConnectorInteraction` value (e.g. piped through\n// `collapseSignerInteraction`) still type-check. Searching has no session\n// 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\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(sessionId: string, method: string, params: unknown): Promise<unknown>;\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<unknown>;\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 * 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 // 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.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.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 } 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 DeviceEvent,\n UiRequestEvent,\n SdkEvent,\n HardwareEvent,\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 IConnector,\n IHardwareBridge,\n} from './types/connector';\nexport { createBridgedConnector, EConnectorInteraction } 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 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 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.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\nexport type ConnectorEventType =\n | 'device-connect'\n | 'device-disconnect'\n | 'ui-request'\n | 'ui-event'\n | 'app-install-progress';\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\n// All variants share the same payload shape so that emit sites where the\n// `type` is a broad `EConnectorInteraction` value (e.g. piped through\n// `collapseSignerInteraction`) still type-check. Searching has no session\n// 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\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 // OS-level Ledger app install progress. Emitted from inside the connector\n // so the callback ref never has to cross the IHardwareBridge boundary.\n // `progress` is a 0..1 fraction reported by DMK's InstallOrUpdateAppsDeviceAction.\n 'app-install-progress': { sessionId: string; appName: string; progress: number };\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(sessionId: string, method: string, params: unknown): Promise<unknown>;\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<unknown>;\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 * 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 // 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"]}
|
package/dist/index.mjs
CHANGED
|
@@ -15,6 +15,7 @@ var HardwareErrorCode = /* @__PURE__ */ ((HardwareErrorCode2) => {
|
|
|
15
15
|
HardwareErrorCode2[HardwareErrorCode2["DeviceMismatch"] = 10106] = "DeviceMismatch";
|
|
16
16
|
HardwareErrorCode2[HardwareErrorCode2["DeviceAppStuck"] = 10107] = "DeviceAppStuck";
|
|
17
17
|
HardwareErrorCode2[HardwareErrorCode2["ChainNotSupported"] = 10108] = "ChainNotSupported";
|
|
18
|
+
HardwareErrorCode2[HardwareErrorCode2["DeviceOneDeviceOnly"] = 10109] = "DeviceOneDeviceOnly";
|
|
18
19
|
HardwareErrorCode2[HardwareErrorCode2["FirmwareTooOld"] = 10200] = "FirmwareTooOld";
|
|
19
20
|
HardwareErrorCode2[HardwareErrorCode2["FirmwareUpdateRequired"] = 10201] = "FirmwareUpdateRequired";
|
|
20
21
|
HardwareErrorCode2[HardwareErrorCode2["TransportError"] = 10300] = "TransportError";
|
|
@@ -28,6 +29,7 @@ var HardwareErrorCode = /* @__PURE__ */ ((HardwareErrorCode2) => {
|
|
|
28
29
|
HardwareErrorCode2[HardwareErrorCode2["AppNotInstalled"] = 10500] = "AppNotInstalled";
|
|
29
30
|
HardwareErrorCode2[HardwareErrorCode2["WrongApp"] = 10501] = "WrongApp";
|
|
30
31
|
HardwareErrorCode2[HardwareErrorCode2["AppTooOld"] = 10502] = "AppTooOld";
|
|
32
|
+
HardwareErrorCode2[HardwareErrorCode2["DeviceOutOfMemory"] = 10503] = "DeviceOutOfMemory";
|
|
31
33
|
HardwareErrorCode2[HardwareErrorCode2["EvmBlindSigningRequired"] = 11e3] = "EvmBlindSigningRequired";
|
|
32
34
|
HardwareErrorCode2[HardwareErrorCode2["EvmClearSignPluginMissing"] = 11001] = "EvmClearSignPluginMissing";
|
|
33
35
|
HardwareErrorCode2[HardwareErrorCode2["EvmDataTooLarge"] = 11002] = "EvmDataTooLarge";
|
|
@@ -47,6 +49,7 @@ var ORPHAN_ELIGIBLE_ERROR_CODES = [
|
|
|
47
49
|
10101 /* DeviceDisconnected */,
|
|
48
50
|
10106 /* DeviceMismatch */,
|
|
49
51
|
10107 /* DeviceAppStuck */,
|
|
52
|
+
10109 /* DeviceOneDeviceOnly */,
|
|
50
53
|
10300 /* TransportError */,
|
|
51
54
|
10303 /* DevicePermissionDenied */,
|
|
52
55
|
10304 /* BlePairingTimeout */
|
|
@@ -450,12 +453,16 @@ function enrichErrorMessage(code, originalMessage) {
|
|
|
450
453
|
return `${originalMessage}. Please reconnect the device and try again.`;
|
|
451
454
|
case 10103 /* DeviceLocked */:
|
|
452
455
|
return `${originalMessage}. Please unlock your device and try again.`;
|
|
456
|
+
case 10109 /* DeviceOneDeviceOnly */:
|
|
457
|
+
return `${originalMessage}. Disconnect the extra device and try again.`;
|
|
453
458
|
case 10001 /* UserRejected */:
|
|
454
459
|
return `${originalMessage}. The request was rejected on the device.`;
|
|
455
460
|
case 10501 /* WrongApp */:
|
|
456
461
|
return `${originalMessage}. Please open the correct app on your device.`;
|
|
457
462
|
case 10500 /* AppNotInstalled */:
|
|
458
463
|
return `${originalMessage}. The required app is not installed on the device.`;
|
|
464
|
+
case 10503 /* DeviceOutOfMemory */:
|
|
465
|
+
return `${originalMessage}. Not enough free space on the device. Please uninstall some apps and try again.`;
|
|
459
466
|
case 10302 /* TransportNotAvailable */:
|
|
460
467
|
return `${originalMessage}. Ensure the device bridge/transport is available and running.`;
|
|
461
468
|
case 10200 /* FirmwareTooOld */:
|
package/dist/index.mjs.map
CHANGED
|
@@ -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\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\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.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 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 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.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 model?: 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\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\n// All variants share the same payload shape so that emit sites where the\n// `type` is a broad `EConnectorInteraction` value (e.g. piped through\n// `collapseSignerInteraction`) still type-check. Searching has no session\n// 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\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(sessionId: string, method: string, params: unknown): Promise<unknown>;\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<unknown>;\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 * 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 // 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.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.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\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 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 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.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\nexport type ConnectorEventType =\n | 'device-connect'\n | 'device-disconnect'\n | 'ui-request'\n | 'ui-event'\n | 'app-install-progress';\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\n// All variants share the same payload shape so that emit sites where the\n// `type` is a broad `EConnectorInteraction` value (e.g. piped through\n// `collapseSignerInteraction`) still type-check. Searching has no session\n// 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\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 // OS-level Ledger app install progress. Emitted from inside the connector\n // so the callback ref never has to cross the IHardwareBridge boundary.\n // `progress` is a 0..1 fraction reported by DMK's InstallOrUpdateAppsDeviceAction.\n 'app-install-progress': { sessionId: string; appName: string; progress: number };\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(sessionId: string, method: string, params: unknown): Promise<unknown>;\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<unknown>;\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 * 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 // 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"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onekeyfe/hwk-adapter-core",
|
|
3
|
-
"version": "1.1.27-alpha.
|
|
3
|
+
"version": "1.1.27-alpha.4",
|
|
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": "
|
|
53
|
+
"gitHead": "93d0e7734f8c3a6380be10f74de203f0ba785bb8"
|
|
54
54
|
}
|