@onekeyfe/hd-shared 1.2.0-alpha.98 → 1.2.0
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/HardwareError.d.ts +3 -0
- package/dist/HardwareError.d.ts.map +1 -1
- package/dist/constants.d.ts +20 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/index.d.ts +52 -1
- package/dist/index.js +143 -5
- package/package.json +2 -2
- package/src/HardwareError.test.ts +28 -1
- package/src/HardwareError.ts +21 -0
- package/src/constants.test.ts +100 -0
- package/src/constants.ts +165 -5
package/dist/HardwareError.d.ts
CHANGED
|
@@ -86,6 +86,7 @@ export declare const HardwareErrorCode: {
|
|
|
86
86
|
readonly BleDeviceDisconnected: 720;
|
|
87
87
|
readonly BlePoweredOff: 721;
|
|
88
88
|
readonly BleUnsupported: 722;
|
|
89
|
+
readonly BleUnavailableWhileUsbConnected: 723;
|
|
89
90
|
readonly RuntimeError: 800;
|
|
90
91
|
readonly PinInvalid: 801;
|
|
91
92
|
readonly PinCancelled: 802;
|
|
@@ -124,6 +125,8 @@ export declare const HardwareErrorCode: {
|
|
|
124
125
|
};
|
|
125
126
|
export declare const HardwareErrorCodeMessage: HardwareErrorCodeMessageMapping;
|
|
126
127
|
export declare const TypedError: (hardwareError: ErrorCodeUnion | string, message?: string, params?: any) => HardwareError;
|
|
128
|
+
export declare const isBleStaleBondHardwareError: (error: unknown) => boolean;
|
|
129
|
+
export declare const isBleStaleBondErrorText: (text: string) => boolean;
|
|
127
130
|
export declare const serializeError: (payload: any) => any;
|
|
128
131
|
export declare const CreateErrorByMessage: (message: string) => HardwareError;
|
|
129
132
|
export declare const CreateHardwareErrorByBridgeError: (raw: string) => HardwareError;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HardwareError.d.ts","sourceRoot":"","sources":["../src/HardwareError.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,OAAO,CAAC,OAAO,iBAAiB,CAAC,CAAC;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,GAAG,CAAC;CACd;AAED,KAAK,OAAO,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;AAE5C,KAAK,+BAA+B,GAAG;KAAG,CAAC,IAAI,OAAO,CAAC,OAAO,iBAAiB,CAAC,GAAG,MAAM;CAAE,CAAC;AAE5F,KAAK,cAAc,GAAG,OAAO,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAsCxD,qBAAa,aAAc,SAAQ,KAAK;IACtC,SAAS,EAAE,cAAc,CAAkC;IAE3D,OAAO,SAAM;IAEb,MAAM,EAAE,GAAG,CAAM;gBAEL,aAAa,EAAE,cAAc,GAAG,MAAM;CAmBnD;AAED,eAAO,MAAM,iBAAiB
|
|
1
|
+
{"version":3,"file":"HardwareError.d.ts","sourceRoot":"","sources":["../src/HardwareError.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,OAAO,CAAC,OAAO,iBAAiB,CAAC,CAAC;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,GAAG,CAAC;CACd;AAED,KAAK,OAAO,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;AAE5C,KAAK,+BAA+B,GAAG;KAAG,CAAC,IAAI,OAAO,CAAC,OAAO,iBAAiB,CAAC,GAAG,MAAM;CAAE,CAAC;AAE5F,KAAK,cAAc,GAAG,OAAO,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAsCxD,qBAAa,aAAc,SAAQ,KAAK;IACtC,SAAS,EAAE,cAAc,CAAkC;IAE3D,OAAO,SAAM;IAEb,MAAM,EAAE,GAAG,CAAM;gBAEL,aAAa,EAAE,cAAc,GAAG,MAAM;CAmBnD;AAED,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAybpB,CAAC;AAEX,eAAO,MAAM,wBAAwB,EAAE,+BAsJ7B,CAAC;AAEX,eAAO,MAAM,UAAU,kBACN,cAAc,GAAG,MAAM,YAC5B,MAAM,WACP,GAAG,kBAMb,CAAC;AAEF,eAAO,MAAM,2BAA2B,UAAW,OAAO,KAAG,OAM5D,CAAC;AAEF,eAAO,MAAM,uBAAuB,SAAU,MAAM,KAAG,OAQtD,CAAC;AAEF,eAAO,MAAM,cAAc,YAAa,GAAG,QAe1C,CAAC;AAEF,eAAO,MAAM,oBAAoB,YAAa,MAAM,KAAG,aAOtD,CAAC;AAGF,eAAO,MAAM,gCAAgC,QAAS,MAAM,KAAG,aAQ9D,CAAC;AAEF,QAAA,MAAM,uCAAuC;oBAM3B,MAAM;oBACN,MAAM;;;mBAcvB,CAAC;AAEF,QAAA,MAAM,sCAAsC;oBAM1B,MAAM;oBACN,MAAM;;;mBAcvB,CAAC;AAEF,QAAA,MAAM,yCAAyC,cAClC,MAAM,GAAG,SAAS,YACnB,MAAM,GAAG,SAAS,iBACb,CAAC,UAAU,GAAG,KAAK,CAAC,EAAE,oBACnB;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,kBAsBF,CAAC;AAEF,QAAA,MAAM,6BAA6B,mBACjB,MAAM,qBACH,MAAM,eACZ,MAAM,kBAQpB,CAAC;AAEF,QAAA,MAAM,4BAA4B,aACtB,MAAM,aACL,MAAM,cACL,MAAM,cACN,MAAM,aACP,MAAM,kBAWlB,CAAC;AAEF,QAAA,MAAM,iCAAiC,eAAgB,MAAM,gBAAgB,aAAa,kBAItF,CAAC;AAEL,OAAO,EACL,uCAAuC,EACvC,sCAAsC,EACtC,yCAAyC,EACzC,6BAA6B,EAC7B,4BAA4B,EAC5B,iCAAiC,GAClC,CAAC"}
|
package/dist/constants.d.ts
CHANGED
|
@@ -8,6 +8,10 @@ export declare const ONEKEY_WEBUSB_FILTER: {
|
|
|
8
8
|
vendorId: number;
|
|
9
9
|
productId: number;
|
|
10
10
|
}[];
|
|
11
|
+
export declare const ONEKEY_PROTOCOL_V2_USB_IDS: readonly [{
|
|
12
|
+
readonly vendorId: 4617;
|
|
13
|
+
readonly productId: 20300;
|
|
14
|
+
}];
|
|
11
15
|
type WebUsbIdentityDescriptor = {
|
|
12
16
|
vendorId?: number;
|
|
13
17
|
productId?: number;
|
|
@@ -42,11 +46,23 @@ export declare enum EOneKeyBleMessageKeys {
|
|
|
42
46
|
NOBLE_BLE_MTU_CHANGED = "$onekey-noble-ble-mtu-changed",
|
|
43
47
|
NOBLE_BLE_CANCEL_PAIRING = "$onekey-noble-ble-cancel-pairing"
|
|
44
48
|
}
|
|
49
|
+
export declare enum EBleDisconnectReason {
|
|
50
|
+
DeviceDisconnected = "device-disconnected",
|
|
51
|
+
IdleKeepAlive = "idle-keep-alive"
|
|
52
|
+
}
|
|
45
53
|
export declare const ONEKEY_SERVICE_UUID = "00000001-0000-1000-8000-00805f9b34fb";
|
|
46
54
|
export declare const ONEKEY_WRITE_CHARACTERISTIC_UUID = "00000002-0000-1000-8000-00805f9b34fb";
|
|
47
55
|
export declare const ONEKEY_NOTIFY_CHARACTERISTIC_UUID = "00000003-0000-1000-8000-00805f9b34fb";
|
|
48
56
|
export declare const isHeaderChunk: (chunk: Buffer | Uint8Array) => boolean;
|
|
49
57
|
export declare const isOnekeyDevice: (name: string | null, id?: string) => boolean;
|
|
58
|
+
export declare const inferProtocolHintFromUsbId: (vendorId?: number | null, productId?: number | null) => "V2" | undefined;
|
|
59
|
+
type UsbDevicePathInput = {
|
|
60
|
+
serialNumber?: string | null;
|
|
61
|
+
vendorId?: number;
|
|
62
|
+
productId?: number;
|
|
63
|
+
productName?: string | null;
|
|
64
|
+
};
|
|
65
|
+
export declare const resolveOneKeyUsbDevicePath: (device: UsbDevicePathInput) => string | undefined;
|
|
50
66
|
type BluetoothDeviceIdentity = {
|
|
51
67
|
id?: string;
|
|
52
68
|
name?: string | null;
|
|
@@ -57,7 +73,11 @@ export declare const normalizeBleUuid: (uuid?: string | null) => string;
|
|
|
57
73
|
export declare const createKnownBleUuidAliases: (uuid: string) => ReadonlySet<string>;
|
|
58
74
|
export declare const matchesKnownBleUuid: (actualUuid: string | null | undefined, aliases: ReadonlySet<string>) => boolean;
|
|
59
75
|
export declare const isPro2FindMyAdvertisementName: (value?: string | null) => boolean;
|
|
76
|
+
export declare const normalizePro2FindMyAdvertisementName: (value: string) => string;
|
|
77
|
+
export declare const canonicalizePro2BleAdvertisementName: (value: string) => string;
|
|
78
|
+
export declare const isSameOnekeyBleName: (left?: string | null, right?: string | null) => boolean;
|
|
60
79
|
export declare const hasOnekeyCommunicationService: (serviceUuids: Array<string | null | undefined> | null | undefined) => boolean;
|
|
80
|
+
export declare const isPro2FamilyBleName: (value?: string | null) => boolean;
|
|
61
81
|
export declare const isOnekeyBluetoothDevice: ({ id, name, localName, serviceUuids, }: BluetoothDeviceIdentity) => boolean;
|
|
62
82
|
export {};
|
|
63
83
|
//# sourceMappingURL=constants.d.ts.map
|
package/dist/constants.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":";AAEA,eAAO,MAAM,yBAAyB;;;CAG5B,CAAC;AAEX,MAAM,MAAM,uBAAuB,GACjC,CAAC,OAAO,yBAAyB,CAAC,CAAC,MAAM,OAAO,yBAAyB,CAAC,CAAC;AAE7E,eAAO,MAAM,oBAAoB;;;GAOhC,CAAC;
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,11 @@ declare const ONEKEY_WEBUSB_FILTER: {
|
|
|
7
7
|
vendorId: number;
|
|
8
8
|
productId: number;
|
|
9
9
|
}[];
|
|
10
|
+
/** USB IDs whose first probe should be Protocol V2. Shared Pro/Touch PIDs stay unhinted. */
|
|
11
|
+
declare const ONEKEY_PROTOCOL_V2_USB_IDS: readonly [{
|
|
12
|
+
readonly vendorId: 4617;
|
|
13
|
+
readonly productId: 20300;
|
|
14
|
+
}];
|
|
10
15
|
type WebUsbIdentityDescriptor = {
|
|
11
16
|
vendorId?: number;
|
|
12
17
|
productId?: number;
|
|
@@ -49,11 +54,33 @@ declare enum EOneKeyBleMessageKeys {
|
|
|
49
54
|
NOBLE_BLE_MTU_CHANGED = "$onekey-noble-ble-mtu-changed",
|
|
50
55
|
NOBLE_BLE_CANCEL_PAIRING = "$onekey-noble-ble-cancel-pairing"
|
|
51
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Why a BLE link went down, carried on BLE_DEVICE_DISCONNECTED.
|
|
59
|
+
*
|
|
60
|
+
* The main process frees an idle link on its own keep-alive timer, which is an
|
|
61
|
+
* internal optimisation the device knows nothing about — consumers must not
|
|
62
|
+
* treat it as "the device is gone". Only DeviceDisconnected means the
|
|
63
|
+
* peripheral actually dropped.
|
|
64
|
+
*/
|
|
65
|
+
declare enum EBleDisconnectReason {
|
|
66
|
+
/** Unsolicited peripheral drop: powered off, out of range, cable/BLE lost. */
|
|
67
|
+
DeviceDisconnected = "device-disconnected",
|
|
68
|
+
/** Main-process keep-alive timer released an idle link; device still present. */
|
|
69
|
+
IdleKeepAlive = "idle-keep-alive"
|
|
70
|
+
}
|
|
52
71
|
declare const ONEKEY_SERVICE_UUID = "00000001-0000-1000-8000-00805f9b34fb";
|
|
53
72
|
declare const ONEKEY_WRITE_CHARACTERISTIC_UUID = "00000002-0000-1000-8000-00805f9b34fb";
|
|
54
73
|
declare const ONEKEY_NOTIFY_CHARACTERISTIC_UUID = "00000003-0000-1000-8000-00805f9b34fb";
|
|
55
74
|
declare const isHeaderChunk: (chunk: Buffer | Uint8Array) => boolean;
|
|
56
75
|
declare const isOnekeyDevice: (name: string | null, id?: string) => boolean;
|
|
76
|
+
declare const inferProtocolHintFromUsbId: (vendorId?: number | null, productId?: number | null) => "V2" | undefined;
|
|
77
|
+
type UsbDevicePathInput = {
|
|
78
|
+
serialNumber?: string | null;
|
|
79
|
+
vendorId?: number;
|
|
80
|
+
productId?: number;
|
|
81
|
+
productName?: string | null;
|
|
82
|
+
};
|
|
83
|
+
declare const resolveOneKeyUsbDevicePath: (device: UsbDevicePathInput) => string | undefined;
|
|
57
84
|
type BluetoothDeviceIdentity = {
|
|
58
85
|
id?: string;
|
|
59
86
|
name?: string | null;
|
|
@@ -64,7 +91,24 @@ declare const normalizeBleUuid: (uuid?: string | null) => string;
|
|
|
64
91
|
declare const createKnownBleUuidAliases: (uuid: string) => ReadonlySet<string>;
|
|
65
92
|
declare const matchesKnownBleUuid: (actualUuid: string | null | undefined, aliases: ReadonlySet<string>) => boolean;
|
|
66
93
|
declare const isPro2FindMyAdvertisementName: (value?: string | null) => boolean;
|
|
94
|
+
declare const normalizePro2FindMyAdvertisementName: (value: string) => string;
|
|
95
|
+
/**
|
|
96
|
+
* Current Pro2 advertisements use "Pro 2 XXXX". Older firmware used "Pro2 XXXX".
|
|
97
|
+
* Discovery and DeviceInfo both go through this helper so the public BLE name
|
|
98
|
+
* stays on the spaced form without changing OneKey Pro / Neo names.
|
|
99
|
+
*
|
|
100
|
+
* Match the compact Pro2 form first. A leading "Pro 2" regex would also eat the
|
|
101
|
+
* first digit of a OneKey Pro suffix such as "Pro 22D8" or "Pro 2D8F".
|
|
102
|
+
*/
|
|
103
|
+
declare const canonicalizePro2BleAdvertisementName: (value: string) => string;
|
|
104
|
+
declare const isSameOnekeyBleName: (left?: string | null, right?: string | null) => boolean;
|
|
67
105
|
declare const hasOnekeyCommunicationService: (serviceUuids: Array<string | null | undefined> | null | undefined) => boolean;
|
|
106
|
+
/**
|
|
107
|
+
* Protocol V2 family (Pro2 / Neo) by advertised BLE name. Callers use it to
|
|
108
|
+
* pick a connection strategy: this family also advertises under Find My names
|
|
109
|
+
* that carry no OneKey service UUID, so a scan cannot always see it.
|
|
110
|
+
*/
|
|
111
|
+
declare const isPro2FamilyBleName: (value?: string | null) => boolean;
|
|
68
112
|
declare const isOnekeyBluetoothDevice: ({ id, name, localName, serviceUuids, }: BluetoothDeviceIdentity) => boolean;
|
|
69
113
|
|
|
70
114
|
type Deferred<T, I = any, D = any> = {
|
|
@@ -316,6 +360,7 @@ declare const HardwareErrorCode: {
|
|
|
316
360
|
readonly BleDeviceDisconnected: 720;
|
|
317
361
|
readonly BlePoweredOff: 721;
|
|
318
362
|
readonly BleUnsupported: 722;
|
|
363
|
+
readonly BleUnavailableWhileUsbConnected: 723;
|
|
319
364
|
/**
|
|
320
365
|
* Hardware runtiome errors
|
|
321
366
|
*/
|
|
@@ -458,6 +503,8 @@ declare const HardwareErrorCode: {
|
|
|
458
503
|
};
|
|
459
504
|
declare const HardwareErrorCodeMessage: HardwareErrorCodeMessageMapping;
|
|
460
505
|
declare const TypedError: (hardwareError: ErrorCodeUnion | string, message?: string, params?: any) => HardwareError;
|
|
506
|
+
declare const isBleStaleBondHardwareError: (error: unknown) => boolean;
|
|
507
|
+
declare const isBleStaleBondErrorText: (text: string) => boolean;
|
|
461
508
|
declare const serializeError: (payload: any) => any;
|
|
462
509
|
declare const CreateErrorByMessage: (message: string) => HardwareError;
|
|
463
510
|
declare const CreateHardwareErrorByBridgeError: (raw: string) => HardwareError;
|
|
@@ -493,6 +540,8 @@ declare const HardwareError$1_HardwareError: typeof HardwareError;
|
|
|
493
540
|
declare const HardwareError$1_HardwareErrorCode: typeof HardwareErrorCode;
|
|
494
541
|
declare const HardwareError$1_HardwareErrorCodeMessage: typeof HardwareErrorCodeMessage;
|
|
495
542
|
declare const HardwareError$1_TypedError: typeof TypedError;
|
|
543
|
+
declare const HardwareError$1_isBleStaleBondHardwareError: typeof isBleStaleBondHardwareError;
|
|
544
|
+
declare const HardwareError$1_isBleStaleBondErrorText: typeof isBleStaleBondErrorText;
|
|
496
545
|
declare const HardwareError$1_serializeError: typeof serializeError;
|
|
497
546
|
declare const HardwareError$1_CreateErrorByMessage: typeof CreateErrorByMessage;
|
|
498
547
|
declare const HardwareError$1_CreateHardwareErrorByBridgeError: typeof CreateHardwareErrorByBridgeError;
|
|
@@ -509,6 +558,8 @@ declare namespace HardwareError$1 {
|
|
|
509
558
|
HardwareError$1_HardwareErrorCode as HardwareErrorCode,
|
|
510
559
|
HardwareError$1_HardwareErrorCodeMessage as HardwareErrorCodeMessage,
|
|
511
560
|
HardwareError$1_TypedError as TypedError,
|
|
561
|
+
HardwareError$1_isBleStaleBondHardwareError as isBleStaleBondHardwareError,
|
|
562
|
+
HardwareError$1_isBleStaleBondErrorText as isBleStaleBondErrorText,
|
|
512
563
|
HardwareError$1_serializeError as serializeError,
|
|
513
564
|
HardwareError$1_CreateErrorByMessage as CreateErrorByMessage,
|
|
514
565
|
HardwareError$1_CreateHardwareErrorByBridgeError as CreateHardwareErrorByBridgeError,
|
|
@@ -529,4 +580,4 @@ declare enum EDeviceType {
|
|
|
529
580
|
Neo = "neo"
|
|
530
581
|
}
|
|
531
582
|
|
|
532
|
-
export { CreateErrorByMessage, CreateHardwareErrorByBridgeError, Deferred, EDeviceType, EFirmwareType, EOneKeyBleMessageKeys, HardwareError$1 as ERRORS, ERROR_CODES_REQUIRE_DISCONNECT, ERROR_CODES_REQUIRE_RELEASE, HARDWARE_CONNECT_PROTOCOL, HardwareConnectProtocol, HardwareError, HardwareErrorCode, HardwareErrorCodeMessage, IHardwareError, ONEKEY_NOTIFY_CHARACTERISTIC_UUID, ONEKEY_SERVICE_UUID, ONEKEY_WEBUSB_FILTER, ONEKEY_WRITE_CHARACTERISTIC_UUID, TypedError, createDefectiveFirmwareError, createDeferred, createDeprecatedHardwareError, createDeviceNotSupportMethodError, createKnownBleUuidAliases, createNeedUpgradeFirmwareHardwareError, createNewFirmwareForceUpdateHardwareError, createNewFirmwareUnReleaseHardwareError, hasOnekeyCommunicationService, isHeaderChunk, isKnownTrezorWebUsbDevice, isOnekeyBluetoothDevice, isOnekeyDevice, isPro2FindMyAdvertisementName, matchesKnownBleUuid, normalizeBleUuid, serializeError, wait };
|
|
583
|
+
export { CreateErrorByMessage, CreateHardwareErrorByBridgeError, Deferred, EBleDisconnectReason, EDeviceType, EFirmwareType, EOneKeyBleMessageKeys, HardwareError$1 as ERRORS, ERROR_CODES_REQUIRE_DISCONNECT, ERROR_CODES_REQUIRE_RELEASE, HARDWARE_CONNECT_PROTOCOL, HardwareConnectProtocol, HardwareError, HardwareErrorCode, HardwareErrorCodeMessage, IHardwareError, ONEKEY_NOTIFY_CHARACTERISTIC_UUID, ONEKEY_PROTOCOL_V2_USB_IDS, ONEKEY_SERVICE_UUID, ONEKEY_WEBUSB_FILTER, ONEKEY_WRITE_CHARACTERISTIC_UUID, TypedError, canonicalizePro2BleAdvertisementName, createDefectiveFirmwareError, createDeferred, createDeprecatedHardwareError, createDeviceNotSupportMethodError, createKnownBleUuidAliases, createNeedUpgradeFirmwareHardwareError, createNewFirmwareForceUpdateHardwareError, createNewFirmwareUnReleaseHardwareError, hasOnekeyCommunicationService, inferProtocolHintFromUsbId, isBleStaleBondErrorText, isBleStaleBondHardwareError, isHeaderChunk, isKnownTrezorWebUsbDevice, isOnekeyBluetoothDevice, isOnekeyDevice, isPro2FamilyBleName, isPro2FindMyAdvertisementName, isSameOnekeyBleName, matchesKnownBleUuid, normalizeBleUuid, normalizePro2FindMyAdvertisementName, resolveOneKeyUsbDevicePath, serializeError, wait };
|
package/dist/index.js
CHANGED
|
@@ -135,6 +135,7 @@ const HardwareErrorCode = {
|
|
|
135
135
|
BleDeviceDisconnected: 720,
|
|
136
136
|
BlePoweredOff: 721,
|
|
137
137
|
BleUnsupported: 722,
|
|
138
|
+
BleUnavailableWhileUsbConnected: 723,
|
|
138
139
|
RuntimeError: 800,
|
|
139
140
|
PinInvalid: 801,
|
|
140
141
|
PinCancelled: 802,
|
|
@@ -242,6 +243,7 @@ const HardwareErrorCodeMessage = {
|
|
|
242
243
|
[HardwareErrorCode.BleDeviceDisconnected]: 'Device disconnected',
|
|
243
244
|
[HardwareErrorCode.BlePoweredOff]: 'Bluetooth is turned off',
|
|
244
245
|
[HardwareErrorCode.BleUnsupported]: 'Bluetooth is not supported on this device',
|
|
246
|
+
[HardwareErrorCode.BleUnavailableWhileUsbConnected]: 'Bluetooth is unavailable while USB is connected. Unplug USB and try again.',
|
|
245
247
|
[HardwareErrorCode.RuntimeError]: 'Runtime error',
|
|
246
248
|
[HardwareErrorCode.PinInvalid]: 'Pin invalid',
|
|
247
249
|
[HardwareErrorCode.PinCancelled]: 'Pin cancelled',
|
|
@@ -284,6 +286,18 @@ const TypedError = (hardwareError, message, params) => {
|
|
|
284
286
|
}
|
|
285
287
|
return new HardwareError({ errorCode: hardwareError, message: message !== null && message !== void 0 ? message : '', params });
|
|
286
288
|
};
|
|
289
|
+
const isBleStaleBondHardwareError = (error) => {
|
|
290
|
+
const code = error === null || error === void 0 ? void 0 : error.errorCode;
|
|
291
|
+
return (code === HardwareErrorCode.BleDeviceBondError ||
|
|
292
|
+
code === HardwareErrorCode.BlePeerRemovedPairingInformation);
|
|
293
|
+
};
|
|
294
|
+
const isBleStaleBondErrorText = (text) => {
|
|
295
|
+
const value = text.toLowerCase();
|
|
296
|
+
return (value.includes('encryption is insufficient') ||
|
|
297
|
+
value.includes('insufficient encryption') ||
|
|
298
|
+
value.includes('peer removed pairing information') ||
|
|
299
|
+
value.includes('gatt_insuf_authentication'));
|
|
300
|
+
};
|
|
287
301
|
const serializeError = (payload) => {
|
|
288
302
|
if (payload && payload.error instanceof HardwareError) {
|
|
289
303
|
return {
|
|
@@ -375,6 +389,8 @@ var HardwareError$1 = /*#__PURE__*/Object.freeze({
|
|
|
375
389
|
HardwareErrorCode: HardwareErrorCode,
|
|
376
390
|
HardwareErrorCodeMessage: HardwareErrorCodeMessage,
|
|
377
391
|
TypedError: TypedError,
|
|
392
|
+
isBleStaleBondHardwareError: isBleStaleBondHardwareError,
|
|
393
|
+
isBleStaleBondErrorText: isBleStaleBondErrorText,
|
|
378
394
|
serializeError: serializeError,
|
|
379
395
|
CreateErrorByMessage: CreateErrorByMessage,
|
|
380
396
|
CreateHardwareErrorByBridgeError: CreateHardwareErrorByBridgeError,
|
|
@@ -397,6 +413,7 @@ const ONEKEY_WEBUSB_FILTER = [
|
|
|
397
413
|
{ vendorId: 0x1209, productId: 0x4f4b },
|
|
398
414
|
{ vendorId: 0x1209, productId: 0x4f4c },
|
|
399
415
|
];
|
|
416
|
+
const ONEKEY_PROTOCOL_V2_USB_IDS = [{ vendorId: 0x1209, productId: 0x4f4c }];
|
|
400
417
|
const TREZOR_WEBUSB_MANUFACTURER_NAMES = new Set(['trezor', 'trezor company', 'satoshilabs']);
|
|
401
418
|
const isKnownTrezorWebUsbDevice = (descriptor) => {
|
|
402
419
|
var _a;
|
|
@@ -447,6 +464,11 @@ exports.EOneKeyBleMessageKeys = void 0;
|
|
|
447
464
|
EOneKeyBleMessageKeys["NOBLE_BLE_MTU_CHANGED"] = "$onekey-noble-ble-mtu-changed";
|
|
448
465
|
EOneKeyBleMessageKeys["NOBLE_BLE_CANCEL_PAIRING"] = "$onekey-noble-ble-cancel-pairing";
|
|
449
466
|
})(exports.EOneKeyBleMessageKeys || (exports.EOneKeyBleMessageKeys = {}));
|
|
467
|
+
exports.EBleDisconnectReason = void 0;
|
|
468
|
+
(function (EBleDisconnectReason) {
|
|
469
|
+
EBleDisconnectReason["DeviceDisconnected"] = "device-disconnected";
|
|
470
|
+
EBleDisconnectReason["IdleKeepAlive"] = "idle-keep-alive";
|
|
471
|
+
})(exports.EBleDisconnectReason || (exports.EBleDisconnectReason = {}));
|
|
450
472
|
const ONEKEY_SERVICE_UUID = '00000001-0000-1000-8000-00805f9b34fb';
|
|
451
473
|
const ONEKEY_WRITE_CHARACTERISTIC_UUID = '00000002-0000-1000-8000-00805f9b34fb';
|
|
452
474
|
const ONEKEY_NOTIFY_CHARACTERISTIC_UUID = '00000003-0000-1000-8000-00805f9b34fb';
|
|
@@ -493,12 +515,36 @@ const isOnekeyDevice = (name, id) => {
|
|
|
493
515
|
return true;
|
|
494
516
|
if (normalizedName.startsWith('touch ') ||
|
|
495
517
|
normalizedName.startsWith('pro ') ||
|
|
496
|
-
normalizedName.startsWith('pro2
|
|
497
|
-
normalizedName.startsWith('neo
|
|
518
|
+
normalizedName.startsWith('pro2') ||
|
|
519
|
+
normalizedName.startsWith('neo')) {
|
|
520
|
+
return true;
|
|
521
|
+
}
|
|
522
|
+
const compactName = compactBleName(normalizedName);
|
|
523
|
+
if (PRO2_COMPACT_NAME_PATTERN.test(compactName) || NEO_COMPACT_NAME_PATTERN.test(compactName)) {
|
|
498
524
|
return true;
|
|
499
525
|
}
|
|
500
526
|
return isOneKeyShortName(normalizedName);
|
|
501
527
|
};
|
|
528
|
+
const inferProtocolHintFromUsbId = (vendorId, productId) => ONEKEY_PROTOCOL_V2_USB_IDS.some(id => id.vendorId === vendorId && id.productId === productId)
|
|
529
|
+
? 'V2'
|
|
530
|
+
: undefined;
|
|
531
|
+
const resolveOneKeyUsbDevicePath = (device) => {
|
|
532
|
+
var _a, _b, _c, _d;
|
|
533
|
+
const serial = (_a = device.serialNumber) === null || _a === void 0 ? void 0 : _a.trim();
|
|
534
|
+
if (serial)
|
|
535
|
+
return serial;
|
|
536
|
+
if (device.vendorId == null && device.productId == null && !device.productName) {
|
|
537
|
+
return undefined;
|
|
538
|
+
}
|
|
539
|
+
const vendorId = ((_b = device.vendorId) !== null && _b !== void 0 ? _b : 0).toString(16).padStart(4, '0');
|
|
540
|
+
const productId = ((_c = device.productId) !== null && _c !== void 0 ? _c : 0).toString(16).padStart(4, '0');
|
|
541
|
+
const product = ((_d = device.productName) !== null && _d !== void 0 ? _d : 'onekey')
|
|
542
|
+
.trim()
|
|
543
|
+
.toLowerCase()
|
|
544
|
+
.replace(/\s+/g, '-')
|
|
545
|
+
.replace(/[^a-z0-9-]/g, '');
|
|
546
|
+
return `usb-${vendorId}-${productId}-${product || 'onekey'}`;
|
|
547
|
+
};
|
|
502
548
|
const BLUETOOTH_BASE_UUID_SUFFIX = '00001000800000805f9b34fb';
|
|
503
549
|
const normalizeBleUuid = (uuid) => (uuid !== null && uuid !== void 0 ? uuid : '').replace(/-/g, '').toLowerCase();
|
|
504
550
|
const createKnownBleUuidAliases = (uuid) => {
|
|
@@ -517,12 +563,95 @@ const createKnownBleUuidAliases = (uuid) => {
|
|
|
517
563
|
const matchesKnownBleUuid = (actualUuid, aliases) => aliases.has(normalizeBleUuid(actualUuid));
|
|
518
564
|
const ONEKEY_COMMUNICATION_SERVICE_ALIASES = createKnownBleUuidAliases(ONEKEY_SERVICE_UUID);
|
|
519
565
|
const FIDO_SERVICE_ALIASES = createKnownBleUuidAliases('0000fffd-0000-1000-8000-00805f9b34fb');
|
|
566
|
+
const PRO2_COMPACT_NAME_PATTERN = /^(?:onekey)?pro2[a-f0-9]{4}$/i;
|
|
567
|
+
const NEO_COMPACT_NAME_PATTERN = /^(?:onekey)?neo[a-f0-9]{4}$/i;
|
|
568
|
+
const FIND_MY_COMPACT_SUFFIXES = [
|
|
569
|
+
'findemy',
|
|
570
|
+
'findem',
|
|
571
|
+
'finde',
|
|
572
|
+
'findmy',
|
|
573
|
+
'findm',
|
|
574
|
+
'find',
|
|
575
|
+
'fin',
|
|
576
|
+
];
|
|
577
|
+
const COMPLETE_FIND_MY_COMPACT_SUFFIXES = ['findemy', 'findmy'];
|
|
578
|
+
const compactBleName = (value) => Array.from(value)
|
|
579
|
+
.filter(character => character !== '-' && character.trim() !== '')
|
|
580
|
+
.join('')
|
|
581
|
+
.toLowerCase();
|
|
582
|
+
const getFindMyCompactSuffix = (compactName) => FIND_MY_COMPACT_SUFFIXES.find(candidate => compactName.endsWith(candidate));
|
|
583
|
+
const getPro2FindMyBaseLength = (value) => {
|
|
584
|
+
const compactName = compactBleName(value);
|
|
585
|
+
const suffix = getFindMyCompactSuffix(compactName);
|
|
586
|
+
if (!suffix)
|
|
587
|
+
return undefined;
|
|
588
|
+
const compactBaseName = compactName.slice(0, -suffix.length);
|
|
589
|
+
return PRO2_COMPACT_NAME_PATTERN.test(compactBaseName) ? compactBaseName.length : undefined;
|
|
590
|
+
};
|
|
520
591
|
const isPro2FindMyAdvertisementName = (value) => {
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
592
|
+
if (!value)
|
|
593
|
+
return false;
|
|
594
|
+
if (getPro2FindMyBaseLength(value) !== undefined)
|
|
595
|
+
return true;
|
|
596
|
+
const compactName = compactBleName(value);
|
|
597
|
+
const suffix = COMPLETE_FIND_MY_COMPACT_SUFFIXES.find(candidate => compactName.endsWith(candidate));
|
|
598
|
+
if (!suffix)
|
|
599
|
+
return false;
|
|
600
|
+
return compactName.slice(0, -suffix.length).includes('pro2');
|
|
601
|
+
};
|
|
602
|
+
const normalizePro2FindMyAdvertisementName = (value) => {
|
|
603
|
+
const baseLength = getPro2FindMyBaseLength(value);
|
|
604
|
+
if (baseLength === undefined)
|
|
605
|
+
return value;
|
|
606
|
+
let compactLength = 0;
|
|
607
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
608
|
+
const character = value[index];
|
|
609
|
+
if (character !== '-' && character.trim() !== '') {
|
|
610
|
+
compactLength += 1;
|
|
611
|
+
if (compactLength === baseLength) {
|
|
612
|
+
return value.slice(0, index + 1).trimEnd();
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
return value;
|
|
617
|
+
};
|
|
618
|
+
const canonicalizePro2BleAdvertisementName = (value) => {
|
|
619
|
+
const withoutFindMy = normalizePro2FindMyAdvertisementName(value);
|
|
620
|
+
const compact = compactBleName(withoutFindMy);
|
|
621
|
+
if (!PRO2_COMPACT_NAME_PATTERN.test(compact))
|
|
622
|
+
return withoutFindMy;
|
|
623
|
+
const match = withoutFindMy.match(/^(onekey\s*)?pro\s*2\s*/i);
|
|
624
|
+
if (!match)
|
|
625
|
+
return withoutFindMy;
|
|
626
|
+
const rest = withoutFindMy.slice(match[0].length);
|
|
627
|
+
const prefix = match[1] ? 'OneKey Pro 2' : 'Pro 2';
|
|
628
|
+
return rest ? `${prefix} ${rest}` : prefix;
|
|
629
|
+
};
|
|
630
|
+
const isSameOnekeyBleName = (left, right) => {
|
|
631
|
+
if (!left || !right)
|
|
632
|
+
return false;
|
|
633
|
+
if (left === right)
|
|
634
|
+
return true;
|
|
635
|
+
return (compactBleName(canonicalizePro2BleAdvertisementName(left)) ===
|
|
636
|
+
compactBleName(canonicalizePro2BleAdvertisementName(right)));
|
|
524
637
|
};
|
|
525
638
|
const hasOnekeyCommunicationService = (serviceUuids) => (serviceUuids !== null && serviceUuids !== void 0 ? serviceUuids : []).some(uuid => matchesKnownBleUuid(uuid, ONEKEY_COMMUNICATION_SERVICE_ALIASES));
|
|
639
|
+
const isPro2FamilyBleName = (value) => {
|
|
640
|
+
if (!value) {
|
|
641
|
+
return false;
|
|
642
|
+
}
|
|
643
|
+
const normalized = value.trim().toLowerCase();
|
|
644
|
+
if (!normalized) {
|
|
645
|
+
return false;
|
|
646
|
+
}
|
|
647
|
+
if (normalized.startsWith('pro2') || normalized.startsWith('neo')) {
|
|
648
|
+
return true;
|
|
649
|
+
}
|
|
650
|
+
const compact = compactBleName(normalized);
|
|
651
|
+
return (PRO2_COMPACT_NAME_PATTERN.test(compact) ||
|
|
652
|
+
NEO_COMPACT_NAME_PATTERN.test(compact) ||
|
|
653
|
+
isPro2FindMyAdvertisementName(value));
|
|
654
|
+
};
|
|
526
655
|
const isOnekeyBluetoothDevice = ({ id, name, localName, serviceUuids, }) => {
|
|
527
656
|
const advertisedServiceUuids = serviceUuids !== null && serviceUuids !== void 0 ? serviceUuids : [];
|
|
528
657
|
if (hasOnekeyCommunicationService(advertisedServiceUuids)) {
|
|
@@ -621,10 +750,12 @@ exports.HardwareError = HardwareError;
|
|
|
621
750
|
exports.HardwareErrorCode = HardwareErrorCode;
|
|
622
751
|
exports.HardwareErrorCodeMessage = HardwareErrorCodeMessage;
|
|
623
752
|
exports.ONEKEY_NOTIFY_CHARACTERISTIC_UUID = ONEKEY_NOTIFY_CHARACTERISTIC_UUID;
|
|
753
|
+
exports.ONEKEY_PROTOCOL_V2_USB_IDS = ONEKEY_PROTOCOL_V2_USB_IDS;
|
|
624
754
|
exports.ONEKEY_SERVICE_UUID = ONEKEY_SERVICE_UUID;
|
|
625
755
|
exports.ONEKEY_WEBUSB_FILTER = ONEKEY_WEBUSB_FILTER;
|
|
626
756
|
exports.ONEKEY_WRITE_CHARACTERISTIC_UUID = ONEKEY_WRITE_CHARACTERISTIC_UUID;
|
|
627
757
|
exports.TypedError = TypedError;
|
|
758
|
+
exports.canonicalizePro2BleAdvertisementName = canonicalizePro2BleAdvertisementName;
|
|
628
759
|
exports.createDefectiveFirmwareError = createDefectiveFirmwareError;
|
|
629
760
|
exports.createDeferred = createDeferred;
|
|
630
761
|
exports.createDeprecatedHardwareError = createDeprecatedHardwareError;
|
|
@@ -634,12 +765,19 @@ exports.createNeedUpgradeFirmwareHardwareError = createNeedUpgradeFirmwareHardwa
|
|
|
634
765
|
exports.createNewFirmwareForceUpdateHardwareError = createNewFirmwareForceUpdateHardwareError;
|
|
635
766
|
exports.createNewFirmwareUnReleaseHardwareError = createNewFirmwareUnReleaseHardwareError;
|
|
636
767
|
exports.hasOnekeyCommunicationService = hasOnekeyCommunicationService;
|
|
768
|
+
exports.inferProtocolHintFromUsbId = inferProtocolHintFromUsbId;
|
|
769
|
+
exports.isBleStaleBondErrorText = isBleStaleBondErrorText;
|
|
770
|
+
exports.isBleStaleBondHardwareError = isBleStaleBondHardwareError;
|
|
637
771
|
exports.isHeaderChunk = isHeaderChunk;
|
|
638
772
|
exports.isKnownTrezorWebUsbDevice = isKnownTrezorWebUsbDevice;
|
|
639
773
|
exports.isOnekeyBluetoothDevice = isOnekeyBluetoothDevice;
|
|
640
774
|
exports.isOnekeyDevice = isOnekeyDevice;
|
|
775
|
+
exports.isPro2FamilyBleName = isPro2FamilyBleName;
|
|
641
776
|
exports.isPro2FindMyAdvertisementName = isPro2FindMyAdvertisementName;
|
|
777
|
+
exports.isSameOnekeyBleName = isSameOnekeyBleName;
|
|
642
778
|
exports.matchesKnownBleUuid = matchesKnownBleUuid;
|
|
643
779
|
exports.normalizeBleUuid = normalizeBleUuid;
|
|
780
|
+
exports.normalizePro2FindMyAdvertisementName = normalizePro2FindMyAdvertisementName;
|
|
781
|
+
exports.resolveOneKeyUsbDevicePath = resolveOneKeyUsbDevicePath;
|
|
644
782
|
exports.serializeError = serializeError;
|
|
645
783
|
exports.wait = wait;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onekeyfe/hd-shared",
|
|
3
|
-
"version": "1.2.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Hardware SDK's shared tool library",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Hardware-SDK",
|
|
@@ -26,5 +26,5 @@
|
|
|
26
26
|
"lint": "eslint .",
|
|
27
27
|
"lint:fix": "eslint . --fix"
|
|
28
28
|
},
|
|
29
|
-
"gitHead": "
|
|
29
|
+
"gitHead": "cc51df0a415bead21304ad1d8bc92b5312c91344"
|
|
30
30
|
}
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
HardwareErrorCode,
|
|
3
|
+
HardwareErrorCodeMessage,
|
|
4
|
+
TypedError,
|
|
5
|
+
serializeError,
|
|
6
|
+
} from './HardwareError';
|
|
2
7
|
|
|
3
8
|
describe('HardwareErrorCode compatibility', () => {
|
|
4
9
|
test('preserves published Protocol V2 values while leaving code 829 unused', () => {
|
|
@@ -6,4 +11,26 @@ describe('HardwareErrorCode compatibility', () => {
|
|
|
6
11
|
expect(HardwareErrorCode.DeviceLocked).toBe(830);
|
|
7
12
|
expect(HardwareErrorCode.WalletSessionInvalid).toBe(831);
|
|
8
13
|
});
|
|
14
|
+
|
|
15
|
+
test('reserves the BLE and USB conflict code for app error mapping', () => {
|
|
16
|
+
expect(HardwareErrorCode.BleUnavailableWhileUsbConnected).toBe(723);
|
|
17
|
+
expect(HardwareErrorCodeMessage[HardwareErrorCode.BleUnavailableWhileUsbConnected]).toBe(
|
|
18
|
+
'Bluetooth is unavailable while USB is connected. Unplug USB and try again.'
|
|
19
|
+
);
|
|
20
|
+
expect(
|
|
21
|
+
serializeError({
|
|
22
|
+
error: TypedError(HardwareErrorCode.BleUnavailableWhileUsbConnected, undefined, {
|
|
23
|
+
failureCode: 'Failure_ProcessError',
|
|
24
|
+
firmwareMessage: 'link disabled',
|
|
25
|
+
}),
|
|
26
|
+
})
|
|
27
|
+
).toEqual({
|
|
28
|
+
code: 723,
|
|
29
|
+
error: 'Bluetooth is unavailable while USB is connected. Unplug USB and try again.',
|
|
30
|
+
params: {
|
|
31
|
+
failureCode: 'Failure_ProcessError',
|
|
32
|
+
firmwareMessage: 'link disabled',
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
});
|
|
9
36
|
});
|
package/src/HardwareError.ts
CHANGED
|
@@ -345,6 +345,7 @@ export const HardwareErrorCode = {
|
|
|
345
345
|
BleDeviceDisconnected: 720,
|
|
346
346
|
BlePoweredOff: 721,
|
|
347
347
|
BleUnsupported: 722,
|
|
348
|
+
BleUnavailableWhileUsbConnected: 723,
|
|
348
349
|
|
|
349
350
|
/**
|
|
350
351
|
* Hardware runtiome errors
|
|
@@ -619,6 +620,8 @@ export const HardwareErrorCodeMessage: HardwareErrorCodeMessageMapping = {
|
|
|
619
620
|
[HardwareErrorCode.BleDeviceDisconnected]: 'Device disconnected',
|
|
620
621
|
[HardwareErrorCode.BlePoweredOff]: 'Bluetooth is turned off',
|
|
621
622
|
[HardwareErrorCode.BleUnsupported]: 'Bluetooth is not supported on this device',
|
|
623
|
+
[HardwareErrorCode.BleUnavailableWhileUsbConnected]:
|
|
624
|
+
'Bluetooth is unavailable while USB is connected. Unplug USB and try again.',
|
|
622
625
|
|
|
623
626
|
/**
|
|
624
627
|
* Runtime Error
|
|
@@ -679,6 +682,24 @@ export const TypedError = (
|
|
|
679
682
|
return new HardwareError({ errorCode: hardwareError, message: message ?? '', params });
|
|
680
683
|
};
|
|
681
684
|
|
|
685
|
+
export const isBleStaleBondHardwareError = (error: unknown): boolean => {
|
|
686
|
+
const code = (error as { errorCode?: unknown })?.errorCode;
|
|
687
|
+
return (
|
|
688
|
+
code === HardwareErrorCode.BleDeviceBondError ||
|
|
689
|
+
code === HardwareErrorCode.BlePeerRemovedPairingInformation
|
|
690
|
+
);
|
|
691
|
+
};
|
|
692
|
+
|
|
693
|
+
export const isBleStaleBondErrorText = (text: string): boolean => {
|
|
694
|
+
const value = text.toLowerCase();
|
|
695
|
+
return (
|
|
696
|
+
value.includes('encryption is insufficient') ||
|
|
697
|
+
value.includes('insufficient encryption') ||
|
|
698
|
+
value.includes('peer removed pairing information') ||
|
|
699
|
+
value.includes('gatt_insuf_authentication')
|
|
700
|
+
);
|
|
701
|
+
};
|
|
702
|
+
|
|
682
703
|
export const serializeError = (payload: any) => {
|
|
683
704
|
if (payload && payload.error instanceof HardwareError) {
|
|
684
705
|
return {
|
package/src/constants.test.ts
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
|
+
canonicalizePro2BleAdvertisementName,
|
|
2
3
|
createKnownBleUuidAliases,
|
|
3
4
|
hasOnekeyCommunicationService,
|
|
5
|
+
inferProtocolHintFromUsbId,
|
|
4
6
|
isKnownTrezorWebUsbDevice,
|
|
5
7
|
isOnekeyBluetoothDevice,
|
|
6
8
|
isOnekeyDevice,
|
|
9
|
+
isPro2FindMyAdvertisementName,
|
|
10
|
+
isSameOnekeyBleName,
|
|
7
11
|
matchesKnownBleUuid,
|
|
12
|
+
normalizePro2FindMyAdvertisementName,
|
|
13
|
+
resolveOneKeyUsbDevicePath,
|
|
8
14
|
} from './constants';
|
|
9
15
|
|
|
10
16
|
describe('hardware device identity filters', () => {
|
|
@@ -12,6 +18,11 @@ describe('hardware device identity filters', () => {
|
|
|
12
18
|
expect(isOnekeyDevice('Touch A1B2')).toBe(true);
|
|
13
19
|
expect(isOnekeyDevice('Pro A1B2')).toBe(true);
|
|
14
20
|
expect(isOnekeyDevice('Neo A1B2')).toBe(true);
|
|
21
|
+
expect(isOnekeyDevice('Pro2A1B2')).toBe(true);
|
|
22
|
+
expect(isOnekeyDevice('Pro 2 A1B2')).toBe(true);
|
|
23
|
+
expect(isOnekeyDevice('OneKeyPro2A1B2')).toBe(true);
|
|
24
|
+
expect(isOnekeyDevice('OneKey Pro 2 A1B2')).toBe(true);
|
|
25
|
+
expect(isOnekeyDevice('Neo22D8')).toBe(true);
|
|
15
26
|
expect(isOnekeyDevice('K1234')).toBe(true);
|
|
16
27
|
expect(isOnekeyDevice('S8')).toBe(true);
|
|
17
28
|
});
|
|
@@ -35,6 +46,12 @@ describe('hardware device identity filters', () => {
|
|
|
35
46
|
serviceUuids: ['0001', 'fffd'],
|
|
36
47
|
})
|
|
37
48
|
).toBe(true);
|
|
49
|
+
expect(
|
|
50
|
+
isOnekeyBluetoothDevice({
|
|
51
|
+
name: 'Pro 2 A1B2',
|
|
52
|
+
serviceUuids: ['0001', 'fffd'],
|
|
53
|
+
})
|
|
54
|
+
).toBe(true);
|
|
38
55
|
expect(
|
|
39
56
|
isOnekeyBluetoothDevice({
|
|
40
57
|
localName: 'Pro2 A1B2 - Find My',
|
|
@@ -67,6 +84,63 @@ describe('hardware device identity filters', () => {
|
|
|
67
84
|
serviceUuids: ['fffd'],
|
|
68
85
|
})
|
|
69
86
|
).toBe(false);
|
|
87
|
+
expect(isOnekeyBluetoothDevice({ name: 'Pro2 - Find My' })).toBe(false);
|
|
88
|
+
expect(isOnekeyBluetoothDevice({ name: 'Pro2 G12Z - Find My' })).toBe(false);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('uses a broad Find My guard without broadening public name normalization', () => {
|
|
92
|
+
expect(isPro2FindMyAdvertisementName('Pro2 Griffin - Find My')).toBe(true);
|
|
93
|
+
expect(isPro2FindMyAdvertisementName('Pro2 Griffin')).toBe(false);
|
|
94
|
+
expect(isPro2FindMyAdvertisementName('Pro2 22D8 - Find My')).toBe(true);
|
|
95
|
+
expect(normalizePro2FindMyAdvertisementName('Pro2 Griffin - Find My')).toBe(
|
|
96
|
+
'Pro2 Griffin - Find My'
|
|
97
|
+
);
|
|
98
|
+
expect(normalizePro2FindMyAdvertisementName('Pro2 22D8 - Find My')).toBe('Pro2 22D8');
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it.each([
|
|
102
|
+
['Pro2 A1B2 - Find My', 'Pro2 A1B2'],
|
|
103
|
+
['Pro2 5E9D - Finde My', 'Pro2 5E9D'],
|
|
104
|
+
[' OneKey Pro 2 A1B2 Find My ', ' OneKey Pro 2 A1B2'],
|
|
105
|
+
['OneKey Pro-2 22D8--Find-My', 'OneKey Pro-2 22D8'],
|
|
106
|
+
['Pro2 22D8FindMy', 'Pro2 22D8'],
|
|
107
|
+
['Pro2 22D8 - Fin', 'Pro2 22D8'],
|
|
108
|
+
['Pro2 22D8FindM', 'Pro2 22D8'],
|
|
109
|
+
[`Pro2 22D8${'\t'.repeat(10_000)}Find My`, 'Pro2 22D8'],
|
|
110
|
+
['Pro2 A1B2', 'Pro2 A1B2'],
|
|
111
|
+
['Pro2 Griffin', 'Pro2 Griffin'],
|
|
112
|
+
['Find My', 'Find My'],
|
|
113
|
+
])('normalizes the public Pro2 advertisement name %s', (name, expected) => {
|
|
114
|
+
expect(normalizePro2FindMyAdvertisementName(name)).toBe(expected);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it.each([
|
|
118
|
+
['Pro2 A1B2', 'Pro 2 A1B2'],
|
|
119
|
+
['Pro2A1B2', 'Pro 2 A1B2'],
|
|
120
|
+
['Pro 2 A1B2', 'Pro 2 A1B2'],
|
|
121
|
+
['Pro 2 0088', 'Pro 2 0088'],
|
|
122
|
+
['Pro2 22D8 - Find My', 'Pro 2 22D8'],
|
|
123
|
+
['Pro 2 A1B2 - Find My', 'Pro 2 A1B2'],
|
|
124
|
+
['OneKeyPro2A1B2', 'OneKey Pro 2 A1B2'],
|
|
125
|
+
['OneKey Pro 2 A1B2', 'OneKey Pro 2 A1B2'],
|
|
126
|
+
['OneKey Pro 2', 'OneKey Pro 2'],
|
|
127
|
+
['Pro A1B2', 'Pro A1B2'],
|
|
128
|
+
['Pro 22D8', 'Pro 22D8'],
|
|
129
|
+
['Pro 2D8F', 'Pro 2D8F'],
|
|
130
|
+
['OneKey Pro 22D8', 'OneKey Pro 22D8'],
|
|
131
|
+
['Neo 22D8', 'Neo 22D8'],
|
|
132
|
+
])('canonicalizes the public Pro2 advertisement name %s', (name, expected) => {
|
|
133
|
+
expect(canonicalizePro2BleAdvertisementName(name)).toBe(expected);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it('treats compact and spaced Pro2 BLE names as the same device', () => {
|
|
137
|
+
expect(isSameOnekeyBleName('Pro2 6136', 'Pro 2 6136')).toBe(true);
|
|
138
|
+
expect(isSameOnekeyBleName('Pro2 6136 - Find My', 'Pro 2 6136')).toBe(true);
|
|
139
|
+
expect(isSameOnekeyBleName('Pro 2 6136', 'Pro 2 0088')).toBe(false);
|
|
140
|
+
expect(isSameOnekeyBleName('Pro A1B2', 'Pro 2 A1B2')).toBe(false);
|
|
141
|
+
expect(isSameOnekeyBleName('Pro 22D8', 'Pro 22D8')).toBe(true);
|
|
142
|
+
expect(isSameOnekeyBleName('Pro 22D8', 'Pro2 22D8')).toBe(false);
|
|
143
|
+
expect(isSameOnekeyBleName('Pro 22D8', 'Pro 2 22D8')).toBe(false);
|
|
70
144
|
});
|
|
71
145
|
|
|
72
146
|
it('keeps OneKey discovery on the communication service', () => {
|
|
@@ -106,6 +180,32 @@ describe('hardware device identity filters', () => {
|
|
|
106
180
|
expect(hasOnekeyCommunicationService(['abcd0001-1234-5678-9012-abcdefabcdef'])).toBe(false);
|
|
107
181
|
});
|
|
108
182
|
|
|
183
|
+
it('hints Protocol V2 from the current Pro2/Neo USB ID only', () => {
|
|
184
|
+
expect(inferProtocolHintFromUsbId(0x1209, 0x4f4c)).toBe('V2');
|
|
185
|
+
expect(inferProtocolHintFromUsbId(0x1209, 0x53c1)).toBeUndefined();
|
|
186
|
+
expect(inferProtocolHintFromUsbId(0x1209, 0x4f4a)).toBeUndefined();
|
|
187
|
+
expect(inferProtocolHintFromUsbId(0x1209, 0x4f4b)).toBeUndefined();
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it('uses the USB serial when present and synthesizes a path when firmware omits it', () => {
|
|
191
|
+
expect(
|
|
192
|
+
resolveOneKeyUsbDevicePath({
|
|
193
|
+
vendorId: 0x1209,
|
|
194
|
+
productId: 0x4f4c,
|
|
195
|
+
productName: 'OneKey Pro 2',
|
|
196
|
+
serialNumber: 'PRO2-SERIAL',
|
|
197
|
+
})
|
|
198
|
+
).toBe('PRO2-SERIAL');
|
|
199
|
+
expect(
|
|
200
|
+
resolveOneKeyUsbDevicePath({
|
|
201
|
+
vendorId: 0x1209,
|
|
202
|
+
productId: 0x4f4c,
|
|
203
|
+
productName: 'OneKey Neo',
|
|
204
|
+
serialNumber: '',
|
|
205
|
+
})
|
|
206
|
+
).toBe('usb-1209-4f4c-onekey-neo');
|
|
207
|
+
});
|
|
208
|
+
|
|
109
209
|
it('only filters WebUSB descriptors that are explicitly identified as Trezor', () => {
|
|
110
210
|
expect(
|
|
111
211
|
isKnownTrezorWebUsbDevice({
|
package/src/constants.ts
CHANGED
|
@@ -13,10 +13,13 @@ export const ONEKEY_WEBUSB_FILTER = [
|
|
|
13
13
|
{ vendorId: 0x1209, productId: 0x53c1 }, // Classic/Classic1s/Mini/Pro/Touch firmware and legacy Pro2; keep for existing devices
|
|
14
14
|
{ vendorId: 0x1209, productId: 0x4f4a }, // Pro bootloader, Touch bootloader, Pro2
|
|
15
15
|
{ vendorId: 0x1209, productId: 0x4f4b }, // Pro/Touch firmware (Trezor not implemented), Pro2
|
|
16
|
-
{ vendorId: 0x1209, productId: 0x4f4c }, //
|
|
16
|
+
{ vendorId: 0x1209, productId: 0x4f4c }, // Pro2 / Neo current firmware, all modes
|
|
17
17
|
// { vendorId: 0x1209, productId: 0x4f50 }, // Touch Board
|
|
18
18
|
];
|
|
19
19
|
|
|
20
|
+
/** USB IDs whose first probe should be Protocol V2. Shared Pro/Touch PIDs stay unhinted. */
|
|
21
|
+
export const ONEKEY_PROTOCOL_V2_USB_IDS = [{ vendorId: 0x1209, productId: 0x4f4c }] as const;
|
|
22
|
+
|
|
20
23
|
type WebUsbIdentityDescriptor = {
|
|
21
24
|
vendorId?: number;
|
|
22
25
|
productId?: number;
|
|
@@ -98,6 +101,21 @@ export enum EOneKeyBleMessageKeys {
|
|
|
98
101
|
NOBLE_BLE_CANCEL_PAIRING = '$onekey-noble-ble-cancel-pairing',
|
|
99
102
|
}
|
|
100
103
|
|
|
104
|
+
/**
|
|
105
|
+
* Why a BLE link went down, carried on BLE_DEVICE_DISCONNECTED.
|
|
106
|
+
*
|
|
107
|
+
* The main process frees an idle link on its own keep-alive timer, which is an
|
|
108
|
+
* internal optimisation the device knows nothing about — consumers must not
|
|
109
|
+
* treat it as "the device is gone". Only DeviceDisconnected means the
|
|
110
|
+
* peripheral actually dropped.
|
|
111
|
+
*/
|
|
112
|
+
export enum EBleDisconnectReason {
|
|
113
|
+
/** Unsolicited peripheral drop: powered off, out of range, cable/BLE lost. */
|
|
114
|
+
DeviceDisconnected = 'device-disconnected',
|
|
115
|
+
/** Main-process keep-alive timer released an idle link; device still present. */
|
|
116
|
+
IdleKeepAlive = 'idle-keep-alive',
|
|
117
|
+
}
|
|
118
|
+
|
|
101
119
|
export const ONEKEY_SERVICE_UUID = '00000001-0000-1000-8000-00805f9b34fb';
|
|
102
120
|
export const ONEKEY_WRITE_CHARACTERISTIC_UUID = '00000002-0000-1000-8000-00805f9b34fb';
|
|
103
121
|
export const ONEKEY_NOTIFY_CHARACTERISTIC_UUID = '00000003-0000-1000-8000-00805f9b34fb';
|
|
@@ -152,14 +170,47 @@ export const isOnekeyDevice = (name: string | null, id?: string): boolean => {
|
|
|
152
170
|
if (
|
|
153
171
|
normalizedName.startsWith('touch ') ||
|
|
154
172
|
normalizedName.startsWith('pro ') ||
|
|
155
|
-
normalizedName.startsWith('pro2
|
|
156
|
-
normalizedName.startsWith('neo
|
|
173
|
+
normalizedName.startsWith('pro2') ||
|
|
174
|
+
normalizedName.startsWith('neo')
|
|
157
175
|
) {
|
|
158
176
|
return true;
|
|
159
177
|
}
|
|
178
|
+
const compactName = compactBleName(normalizedName);
|
|
179
|
+
if (PRO2_COMPACT_NAME_PATTERN.test(compactName) || NEO_COMPACT_NAME_PATTERN.test(compactName)) {
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
160
182
|
return isOneKeyShortName(normalizedName);
|
|
161
183
|
};
|
|
162
184
|
|
|
185
|
+
export const inferProtocolHintFromUsbId = (vendorId?: number | null, productId?: number | null) =>
|
|
186
|
+
ONEKEY_PROTOCOL_V2_USB_IDS.some(id => id.vendorId === vendorId && id.productId === productId)
|
|
187
|
+
? ('V2' as const)
|
|
188
|
+
: undefined;
|
|
189
|
+
|
|
190
|
+
type UsbDevicePathInput = {
|
|
191
|
+
serialNumber?: string | null;
|
|
192
|
+
vendorId?: number;
|
|
193
|
+
productId?: number;
|
|
194
|
+
productName?: string | null;
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
export const resolveOneKeyUsbDevicePath = (device: UsbDevicePathInput): string | undefined => {
|
|
198
|
+
const serial = device.serialNumber?.trim();
|
|
199
|
+
if (serial) return serial;
|
|
200
|
+
if (device.vendorId == null && device.productId == null && !device.productName) {
|
|
201
|
+
return undefined;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const vendorId = (device.vendorId ?? 0).toString(16).padStart(4, '0');
|
|
205
|
+
const productId = (device.productId ?? 0).toString(16).padStart(4, '0');
|
|
206
|
+
const product = (device.productName ?? 'onekey')
|
|
207
|
+
.trim()
|
|
208
|
+
.toLowerCase()
|
|
209
|
+
.replace(/\s+/g, '-')
|
|
210
|
+
.replace(/[^a-z0-9-]/g, '');
|
|
211
|
+
return `usb-${vendorId}-${productId}-${product || 'onekey'}`;
|
|
212
|
+
};
|
|
213
|
+
|
|
163
214
|
type BluetoothDeviceIdentity = {
|
|
164
215
|
id?: string;
|
|
165
216
|
name?: string | null;
|
|
@@ -195,10 +246,95 @@ export const matchesKnownBleUuid = (
|
|
|
195
246
|
|
|
196
247
|
const ONEKEY_COMMUNICATION_SERVICE_ALIASES = createKnownBleUuidAliases(ONEKEY_SERVICE_UUID);
|
|
197
248
|
const FIDO_SERVICE_ALIASES = createKnownBleUuidAliases('0000fffd-0000-1000-8000-00805f9b34fb');
|
|
249
|
+
const PRO2_COMPACT_NAME_PATTERN = /^(?:onekey)?pro2[a-f0-9]{4}$/i;
|
|
250
|
+
const NEO_COMPACT_NAME_PATTERN = /^(?:onekey)?neo[a-f0-9]{4}$/i;
|
|
251
|
+
const FIND_MY_COMPACT_SUFFIXES = [
|
|
252
|
+
'findemy',
|
|
253
|
+
'findem',
|
|
254
|
+
'finde',
|
|
255
|
+
'findmy',
|
|
256
|
+
'findm',
|
|
257
|
+
'find',
|
|
258
|
+
'fin',
|
|
259
|
+
] as const;
|
|
260
|
+
const COMPLETE_FIND_MY_COMPACT_SUFFIXES = ['findemy', 'findmy'] as const;
|
|
261
|
+
|
|
262
|
+
const compactBleName = (value: string) =>
|
|
263
|
+
Array.from(value)
|
|
264
|
+
.filter(character => character !== '-' && character.trim() !== '')
|
|
265
|
+
.join('')
|
|
266
|
+
.toLowerCase();
|
|
267
|
+
|
|
268
|
+
const getFindMyCompactSuffix = (compactName: string) =>
|
|
269
|
+
FIND_MY_COMPACT_SUFFIXES.find(candidate => compactName.endsWith(candidate));
|
|
270
|
+
|
|
271
|
+
const getPro2FindMyBaseLength = (value: string) => {
|
|
272
|
+
const compactName = compactBleName(value);
|
|
273
|
+
const suffix = getFindMyCompactSuffix(compactName);
|
|
274
|
+
if (!suffix) return undefined;
|
|
275
|
+
|
|
276
|
+
const compactBaseName = compactName.slice(0, -suffix.length);
|
|
277
|
+
return PRO2_COMPACT_NAME_PATTERN.test(compactBaseName) ? compactBaseName.length : undefined;
|
|
278
|
+
};
|
|
198
279
|
|
|
199
280
|
export const isPro2FindMyAdvertisementName = (value?: string | null) => {
|
|
200
|
-
|
|
201
|
-
|
|
281
|
+
if (!value) return false;
|
|
282
|
+
if (getPro2FindMyBaseLength(value) !== undefined) return true;
|
|
283
|
+
|
|
284
|
+
const compactName = compactBleName(value);
|
|
285
|
+
const suffix = COMPLETE_FIND_MY_COMPACT_SUFFIXES.find(candidate =>
|
|
286
|
+
compactName.endsWith(candidate)
|
|
287
|
+
);
|
|
288
|
+
if (!suffix) return false;
|
|
289
|
+
|
|
290
|
+
return compactName.slice(0, -suffix.length).includes('pro2');
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
export const normalizePro2FindMyAdvertisementName = (value: string) => {
|
|
294
|
+
const baseLength = getPro2FindMyBaseLength(value);
|
|
295
|
+
if (baseLength === undefined) return value;
|
|
296
|
+
|
|
297
|
+
let compactLength = 0;
|
|
298
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
299
|
+
const character = value[index];
|
|
300
|
+
if (character !== '-' && character.trim() !== '') {
|
|
301
|
+
compactLength += 1;
|
|
302
|
+
if (compactLength === baseLength) {
|
|
303
|
+
return value.slice(0, index + 1).trimEnd();
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
return value;
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Current Pro2 advertisements use "Pro 2 XXXX". Older firmware used "Pro2 XXXX".
|
|
312
|
+
* Discovery and DeviceInfo both go through this helper so the public BLE name
|
|
313
|
+
* stays on the spaced form without changing OneKey Pro / Neo names.
|
|
314
|
+
*
|
|
315
|
+
* Match the compact Pro2 form first. A leading "Pro 2" regex would also eat the
|
|
316
|
+
* first digit of a OneKey Pro suffix such as "Pro 22D8" or "Pro 2D8F".
|
|
317
|
+
*/
|
|
318
|
+
export const canonicalizePro2BleAdvertisementName = (value: string) => {
|
|
319
|
+
const withoutFindMy = normalizePro2FindMyAdvertisementName(value);
|
|
320
|
+
const compact = compactBleName(withoutFindMy);
|
|
321
|
+
if (!PRO2_COMPACT_NAME_PATTERN.test(compact)) return withoutFindMy;
|
|
322
|
+
|
|
323
|
+
const match = withoutFindMy.match(/^(onekey\s*)?pro\s*2\s*/i);
|
|
324
|
+
if (!match) return withoutFindMy;
|
|
325
|
+
|
|
326
|
+
const rest = withoutFindMy.slice(match[0].length);
|
|
327
|
+
const prefix = match[1] ? 'OneKey Pro 2' : 'Pro 2';
|
|
328
|
+
return rest ? `${prefix} ${rest}` : prefix;
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
export const isSameOnekeyBleName = (left?: string | null, right?: string | null) => {
|
|
332
|
+
if (!left || !right) return false;
|
|
333
|
+
if (left === right) return true;
|
|
334
|
+
return (
|
|
335
|
+
compactBleName(canonicalizePro2BleAdvertisementName(left)) ===
|
|
336
|
+
compactBleName(canonicalizePro2BleAdvertisementName(right))
|
|
337
|
+
);
|
|
202
338
|
};
|
|
203
339
|
|
|
204
340
|
export const hasOnekeyCommunicationService = (
|
|
@@ -208,6 +344,30 @@ export const hasOnekeyCommunicationService = (
|
|
|
208
344
|
matchesKnownBleUuid(uuid, ONEKEY_COMMUNICATION_SERVICE_ALIASES)
|
|
209
345
|
);
|
|
210
346
|
|
|
347
|
+
/**
|
|
348
|
+
* Protocol V2 family (Pro2 / Neo) by advertised BLE name. Callers use it to
|
|
349
|
+
* pick a connection strategy: this family also advertises under Find My names
|
|
350
|
+
* that carry no OneKey service UUID, so a scan cannot always see it.
|
|
351
|
+
*/
|
|
352
|
+
export const isPro2FamilyBleName = (value?: string | null): boolean => {
|
|
353
|
+
if (!value) {
|
|
354
|
+
return false;
|
|
355
|
+
}
|
|
356
|
+
const normalized = value.trim().toLowerCase();
|
|
357
|
+
if (!normalized) {
|
|
358
|
+
return false;
|
|
359
|
+
}
|
|
360
|
+
if (normalized.startsWith('pro2') || normalized.startsWith('neo')) {
|
|
361
|
+
return true;
|
|
362
|
+
}
|
|
363
|
+
const compact = compactBleName(normalized);
|
|
364
|
+
return (
|
|
365
|
+
PRO2_COMPACT_NAME_PATTERN.test(compact) ||
|
|
366
|
+
NEO_COMPACT_NAME_PATTERN.test(compact) ||
|
|
367
|
+
isPro2FindMyAdvertisementName(value)
|
|
368
|
+
);
|
|
369
|
+
};
|
|
370
|
+
|
|
211
371
|
export const isOnekeyBluetoothDevice = ({
|
|
212
372
|
id,
|
|
213
373
|
name,
|