@onekeyfe/hd-shared 1.2.0-alpha.16 → 1.2.0-alpha.161

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.
@@ -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;
@@ -115,7 +116,9 @@ export declare const HardwareErrorCode: {
115
116
  readonly DeviceSettingsLanguageNotSupport: 826;
116
117
  readonly TooManyInputs: 827;
117
118
  readonly PinMismatch: 828;
118
- readonly DeviceLocked: 829;
119
+ readonly DeviceLocked: 830;
120
+ readonly WalletSessionInvalid: 831;
121
+ readonly NftStorageLimitReached: 832;
119
122
  readonly LowlevelTrasnportConnectError: 900;
120
123
  readonly WebDeviceNotFoundOrNeedsPermission: 901;
121
124
  readonly WebDevicePromptAccessError: 902;
@@ -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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4apB,CAAC;AAEX,eAAO,MAAM,wBAAwB,EAAE,+BAiJ7B,CAAC;AAEX,eAAO,MAAM,UAAU,kBACN,cAAc,GAAG,MAAM,YAC5B,MAAM,WACP,GAAG,kBAMb,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"}
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,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"}
@@ -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;
@@ -33,17 +37,44 @@ export declare enum EOneKeyBleMessageKeys {
33
37
  NOBLE_BLE_STOP_SCAN = "$onekey-noble-ble-stop-scan",
34
38
  NOBLE_BLE_GET_DEVICE = "$onekey-noble-ble-get-device",
35
39
  NOBLE_BLE_CONNECT = "$onekey-noble-ble-connect",
40
+ NOBLE_BLE_RELEASE = "$onekey-noble-ble-release",
36
41
  NOBLE_BLE_DISCONNECT = "$onekey-noble-ble-disconnect",
37
42
  NOBLE_BLE_WRITE = "$onekey-noble-ble-write",
38
43
  NOBLE_BLE_SUBSCRIBE = "$onekey-noble-ble-subscribe",
39
44
  NOBLE_BLE_UNSUBSCRIBE = "$onekey-noble-ble-unsubscribe",
40
45
  NOBLE_BLE_NOTIFICATION = "$onekey-noble-ble-notification",
46
+ NOBLE_BLE_MTU_CHANGED = "$onekey-noble-ble-mtu-changed",
41
47
  NOBLE_BLE_CANCEL_PAIRING = "$onekey-noble-ble-cancel-pairing"
42
48
  }
49
+ export declare enum EBleDisconnectReason {
50
+ DeviceDisconnected = "device-disconnected",
51
+ IdleKeepAlive = "idle-keep-alive"
52
+ }
43
53
  export declare const ONEKEY_SERVICE_UUID = "00000001-0000-1000-8000-00805f9b34fb";
44
54
  export declare const ONEKEY_WRITE_CHARACTERISTIC_UUID = "00000002-0000-1000-8000-00805f9b34fb";
45
55
  export declare const ONEKEY_NOTIFY_CHARACTERISTIC_UUID = "00000003-0000-1000-8000-00805f9b34fb";
46
56
  export declare const isHeaderChunk: (chunk: Buffer | Uint8Array) => boolean;
47
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;
66
+ type BluetoothDeviceIdentity = {
67
+ id?: string;
68
+ name?: string | null;
69
+ localName?: string | null;
70
+ serviceUuids?: Array<string | null | undefined> | null;
71
+ };
72
+ export declare const normalizeBleUuid: (uuid?: string | null) => string;
73
+ export declare const createKnownBleUuidAliases: (uuid: string) => ReadonlySet<string>;
74
+ export declare const matchesKnownBleUuid: (actualUuid: string | null | undefined, aliases: ReadonlySet<string>) => boolean;
75
+ export declare const isPro2FindMyAdvertisementName: (value?: string | null) => boolean;
76
+ export declare const normalizePro2FindMyAdvertisementName: (value: string) => string;
77
+ export declare const hasOnekeyCommunicationService: (serviceUuids: Array<string | null | undefined> | null | undefined) => boolean;
78
+ export declare const isOnekeyBluetoothDevice: ({ id, name, localName, serviceUuids, }: BluetoothDeviceIdentity) => boolean;
48
79
  export {};
49
80
  //# sourceMappingURL=constants.d.ts.map
@@ -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;AAEF,KAAK,wBAAwB,GAAG;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC,CAAC;AAIF,eAAO,MAAM,yBAAyB,eAAgB,wBAAwB,KAAG,OAQhF,CAAC;AAMF,eAAO,MAAM,2BAA2B,mDAS9B,CAAC;AAMX,eAAO,MAAM,8BAA8B,qBAGjC,CAAC;AAGX,oBAAY,qBAAqB;IAE/B,UAAU,uBAAuB;IACjC,iBAAiB,8BAA8B;IAC/C,aAAa,0BAA0B;IACvC,kBAAkB,+BAA+B;IACjD,cAAc,2BAA2B;IACzC,oBAAoB,iCAAiC;IAGrD,mBAAmB,gCAAgC;IACnD,oBAAoB,iCAAiC;IAGrD,aAAa,0BAA0B;IACvC,oBAAoB,iCAAiC;IAGrD,uBAAuB,oCAAoC;IAC3D,sBAAsB,mCAAmC;IAGzD,mBAAmB,gCAAgC;IACnD,mBAAmB,gCAAgC;IACnD,oBAAoB,iCAAiC;IACrD,iBAAiB,8BAA8B;IAC/C,oBAAoB,iCAAiC;IACrD,eAAe,4BAA4B;IAC3C,mBAAmB,gCAAgC;IACnD,qBAAqB,kCAAkC;IACvD,sBAAsB,mCAAmC;IACzD,wBAAwB,qCAAqC;CAC9D;AAED,eAAO,MAAM,mBAAmB,yCAAyC,CAAC;AAC1E,eAAO,MAAM,gCAAgC,yCAAyC,CAAC;AACvF,eAAO,MAAM,iCAAiC,yCAAyC,CAAC;AAIxF,eAAO,MAAM,aAAa,UAAW,MAAM,GAAG,UAAU,KAAG,OAa1D,CAAC;AAkBF,eAAO,MAAM,cAAc,SAAU,MAAM,GAAG,IAAI,OAAO,MAAM,KAAG,OAsBjE,CAAC"}
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;AAGF,eAAO,MAAM,0BAA0B;;;EAAqD,CAAC;AAE7F,KAAK,wBAAwB,GAAG;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC,CAAC;AAIF,eAAO,MAAM,yBAAyB,eAAgB,wBAAwB,KAAG,OAQhF,CAAC;AAMF,eAAO,MAAM,2BAA2B,mDAS9B,CAAC;AAMX,eAAO,MAAM,8BAA8B,qBAGjC,CAAC;AAGX,oBAAY,qBAAqB;IAE/B,UAAU,uBAAuB;IACjC,iBAAiB,8BAA8B;IAC/C,aAAa,0BAA0B;IACvC,kBAAkB,+BAA+B;IACjD,cAAc,2BAA2B;IACzC,oBAAoB,iCAAiC;IAGrD,mBAAmB,gCAAgC;IACnD,oBAAoB,iCAAiC;IAGrD,aAAa,0BAA0B;IACvC,oBAAoB,iCAAiC;IAGrD,uBAAuB,oCAAoC;IAC3D,sBAAsB,mCAAmC;IAGzD,mBAAmB,gCAAgC;IACnD,mBAAmB,gCAAgC;IACnD,oBAAoB,iCAAiC;IACrD,iBAAiB,8BAA8B;IAG/C,iBAAiB,8BAA8B;IAC/C,oBAAoB,iCAAiC;IACrD,eAAe,4BAA4B;IAC3C,mBAAmB,gCAAgC;IACnD,qBAAqB,kCAAkC;IACvD,sBAAsB,mCAAmC;IACzD,qBAAqB,kCAAkC;IACvD,wBAAwB,qCAAqC;CAC9D;AAUD,oBAAY,oBAAoB;IAE9B,kBAAkB,wBAAwB;IAE1C,aAAa,oBAAoB;CAClC;AAED,eAAO,MAAM,mBAAmB,yCAAyC,CAAC;AAC1E,eAAO,MAAM,gCAAgC,yCAAyC,CAAC;AACvF,eAAO,MAAM,iCAAiC,yCAAyC,CAAC;AAIxF,eAAO,MAAM,aAAa,UAAW,MAAM,GAAG,UAAU,KAAG,OAa1D,CAAC;AAkBF,eAAO,MAAM,cAAc,SAAU,MAAM,GAAG,IAAI,OAAO,MAAM,KAAG,OA2BjE,CAAC;AAEF,eAAO,MAAM,0BAA0B,cAAe,MAAM,GAAG,IAAI,cAAc,MAAM,GAAG,IAAI,qBAG/E,CAAC;AAEhB,KAAK,kBAAkB,GAAG;IACxB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B,CAAC;AAEF,eAAO,MAAM,0BAA0B,WAAY,kBAAkB,KAAG,MAAM,GAAG,SAehF,CAAC;AAEF,KAAK,uBAAuB,GAAG;IAC7B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,GAAG,IAAI,CAAC;CACxD,CAAC;AAIF,eAAO,MAAM,gBAAgB,UAAW,MAAM,GAAG,IAAI,WACP,CAAC;AAE/C,eAAO,MAAM,yBAAyB,SAAU,MAAM,KAAG,YAAY,MAAM,CAc1E,CAAC;AAEF,eAAO,MAAM,mBAAmB,eAClB,MAAM,GAAG,IAAI,GAAG,SAAS,WAC5B,YAAY,MAAM,CAAC,YACgB,CAAC;AAmC/C,eAAO,MAAM,6BAA6B,WAAY,MAAM,GAAG,IAAI,YAWlE,CAAC;AAEF,eAAO,MAAM,oCAAoC,UAAW,MAAM,WAejE,CAAC;AAEF,eAAO,MAAM,6BAA6B,iBAC1B,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,GAAG,IAAI,GAAG,SAAS,YAIhE,CAAC;AAEJ,eAAO,MAAM,uBAAuB,2CAKjC,uBAAuB,KAAG,OAiB5B,CAAC"}
@@ -6,6 +6,7 @@ export declare enum EDeviceType {
6
6
  Mini = "mini",
7
7
  Touch = "touch",
8
8
  Pro = "pro",
9
- Pro2 = "pro2"
9
+ Pro2 = "pro2",
10
+ Neo = "neo"
10
11
  }
11
12
  //# sourceMappingURL=deviceType.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"deviceType.d.ts","sourceRoot":"","sources":["../src/deviceType.ts"],"names":[],"mappings":"AAAA,oBAAY,WAAW;IACrB,OAAO,YAAY;IACnB,OAAO,YAAY;IACnB,SAAS,cAAc;IACvB,WAAW,gBAAgB;IAC3B,IAAI,SAAS;IACb,KAAK,UAAU;IACf,GAAG,QAAQ;IACX,IAAI,SAAS;CACd"}
1
+ {"version":3,"file":"deviceType.d.ts","sourceRoot":"","sources":["../src/deviceType.ts"],"names":[],"mappings":"AAAA,oBAAY,WAAW;IACrB,OAAO,YAAY;IACnB,OAAO,YAAY;IACnB,SAAS,cAAc;IACvB,WAAW,gBAAgB;IAC3B,IAAI,SAAS;IACb,KAAK,UAAU;IACf,GAAG,QAAQ;IACX,IAAI,SAAS;IACb,GAAG,QAAQ;CACZ"}
package/dist/index.d.ts CHANGED
@@ -7,13 +7,26 @@ 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;
13
18
  manufacturerName?: string | null;
14
19
  };
15
20
  declare const isKnownTrezorWebUsbDevice: (descriptor: WebUsbIdentityDescriptor) => boolean;
21
+ /**
22
+ * Error codes that require device release after occurrence
23
+ * These errors indicate the device is in an invalid state and needs to be released
24
+ */
16
25
  declare const ERROR_CODES_REQUIRE_RELEASE: readonly [106, 107, 109, 112, 805, 801, 802, 812];
26
+ /**
27
+ * Error codes that require device disconnect before release
28
+ * These errors indicate a communication failure that requires full reconnection
29
+ */
17
30
  declare const ERROR_CODES_REQUIRE_DISCONNECT: readonly [106, 805];
18
31
  declare enum EOneKeyBleMessageKeys {
19
32
  BLE_SELECT = "$onekey-ble-select",
@@ -32,18 +45,55 @@ declare enum EOneKeyBleMessageKeys {
32
45
  NOBLE_BLE_STOP_SCAN = "$onekey-noble-ble-stop-scan",
33
46
  NOBLE_BLE_GET_DEVICE = "$onekey-noble-ble-get-device",
34
47
  NOBLE_BLE_CONNECT = "$onekey-noble-ble-connect",
48
+ NOBLE_BLE_RELEASE = "$onekey-noble-ble-release",
35
49
  NOBLE_BLE_DISCONNECT = "$onekey-noble-ble-disconnect",
36
50
  NOBLE_BLE_WRITE = "$onekey-noble-ble-write",
37
51
  NOBLE_BLE_SUBSCRIBE = "$onekey-noble-ble-subscribe",
38
52
  NOBLE_BLE_UNSUBSCRIBE = "$onekey-noble-ble-unsubscribe",
39
53
  NOBLE_BLE_NOTIFICATION = "$onekey-noble-ble-notification",
54
+ NOBLE_BLE_MTU_CHANGED = "$onekey-noble-ble-mtu-changed",
40
55
  NOBLE_BLE_CANCEL_PAIRING = "$onekey-noble-ble-cancel-pairing"
41
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
+ }
42
71
  declare const ONEKEY_SERVICE_UUID = "00000001-0000-1000-8000-00805f9b34fb";
43
72
  declare const ONEKEY_WRITE_CHARACTERISTIC_UUID = "00000002-0000-1000-8000-00805f9b34fb";
44
73
  declare const ONEKEY_NOTIFY_CHARACTERISTIC_UUID = "00000003-0000-1000-8000-00805f9b34fb";
45
74
  declare const isHeaderChunk: (chunk: Buffer | Uint8Array) => boolean;
46
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;
84
+ type BluetoothDeviceIdentity = {
85
+ id?: string;
86
+ name?: string | null;
87
+ localName?: string | null;
88
+ serviceUuids?: Array<string | null | undefined> | null;
89
+ };
90
+ declare const normalizeBleUuid: (uuid?: string | null) => string;
91
+ declare const createKnownBleUuidAliases: (uuid: string) => ReadonlySet<string>;
92
+ declare const matchesKnownBleUuid: (actualUuid: string | null | undefined, aliases: ReadonlySet<string>) => boolean;
93
+ declare const isPro2FindMyAdvertisementName: (value?: string | null) => boolean;
94
+ declare const normalizePro2FindMyAdvertisementName: (value: string) => string;
95
+ declare const hasOnekeyCommunicationService: (serviceUuids: Array<string | null | undefined> | null | undefined) => boolean;
96
+ declare const isOnekeyBluetoothDevice: ({ id, name, localName, serviceUuids, }: BluetoothDeviceIdentity) => boolean;
47
97
 
48
98
  type Deferred<T, I = any, D = any> = {
49
99
  id?: I;
@@ -76,53 +126,201 @@ declare class HardwareError extends Error {
76
126
  constructor(hardwareError: IHardwareError | string);
77
127
  }
78
128
  declare const HardwareErrorCode: {
129
+ /**
130
+ * This error can be thrown when unexpected error occurred and in most cases it is related to implementation bug.
131
+ * Original message is available in message property.
132
+ */
79
133
  readonly UnknownError: 0;
134
+ /**
135
+ * Firmware version mismatch
136
+ */
80
137
  readonly DeviceFwException: 101;
138
+ /**
139
+ * Device unexpected mode
140
+ */
81
141
  readonly DeviceUnexpectedMode: 102;
142
+ /**
143
+ * Device list is not initialized
144
+ */
82
145
  readonly DeviceListNotInitialized: 103;
146
+ /**
147
+ * Please select the connected device
148
+ */
83
149
  readonly SelectDevice: 104;
150
+ /**
151
+ * Device not found
152
+ */
84
153
  readonly DeviceNotFound: 105;
154
+ /**
155
+ * Device is not initialized
156
+ */
85
157
  readonly DeviceInitializeFailed: 106;
158
+ /**
159
+ * Device interrupted from another operation
160
+ */
86
161
  readonly DeviceInterruptedFromOutside: 107;
162
+ /**
163
+ * Device should be in bootloader mode
164
+ */
87
165
  readonly RequiredButInBootloaderMode: 108;
166
+ /**
167
+ * Device interrupted from user
168
+ */
88
169
  readonly DeviceInterruptedFromUser: 109;
170
+ /**
171
+ * Check device id is same
172
+ */
89
173
  readonly DeviceCheckDeviceIdError: 110;
174
+ /**
175
+ * Do not support passphrase
176
+ * @params: { require: string }
177
+ */
90
178
  readonly DeviceNotSupportPassphrase: 111;
91
179
  readonly DeviceCheckPassphraseStateError: 112;
180
+ /**
181
+ * use passphrase, but passphrase is not opened
182
+ */
92
183
  readonly DeviceNotOpenedPassphrase: 113;
184
+ /**
185
+ * not use passphrase, but passphrase is opened
186
+ */
93
187
  readonly DeviceOpenedPassphrase: 114;
188
+ /**
189
+ * Detect hardware that is in bootloader mode and return an error.
190
+ */
94
191
  readonly DeviceDetectInBootloaderMode: 115;
192
+ /**
193
+ * Device not allow in bootloader mode
194
+ */
95
195
  readonly NotAllowInBootloaderMode: 116;
196
+ /**
197
+ * Device is busy
198
+ */
96
199
  readonly DeviceBusy: 117;
200
+ /**
201
+ * Device check unlock type not match error
202
+ */
97
203
  readonly DeviceCheckUnlockTypeError: 118;
204
+ /**
205
+ * Not initialized
206
+ */
98
207
  readonly NotInitialized: 200;
208
+ /**
209
+ * Iframe not initialized
210
+ */
99
211
  readonly IFrameNotInitialized: 300;
212
+ /**
213
+ * iframe repeat initialization
214
+ */
100
215
  readonly IFrameAleradyInitialized: 301;
216
+ /**
217
+ * iframe load failure
218
+ */
101
219
  readonly IFrameLoadFail: 302;
220
+ /**
221
+ * init iframe time out
222
+ */
102
223
  readonly IframeTimeout: 303;
224
+ /**
225
+ * iframe blocked
226
+ */
103
227
  readonly IframeBlocked: 304;
228
+ /**
229
+ * iframe host not trust
230
+ */
104
231
  readonly IframeDistrust: 305;
232
+ /**
233
+ * Runtime errors during method execution
234
+ */
105
235
  readonly CallMethodError: 400;
236
+ /**
237
+ * Method does not responding
238
+ */
106
239
  readonly CallMethodNotResponse: 404;
240
+ /**
241
+ * Call method invalid parameter
242
+ */
107
243
  readonly CallMethodInvalidParameter: 405;
244
+ /**
245
+ * firmware update download failed
246
+ */
108
247
  readonly FirmwareUpdateDownloadFailed: 406;
248
+ /**
249
+ * Call method not supported, need update firmware
250
+ * @params: { current: string, require: string }
251
+ */
109
252
  readonly CallMethodNeedUpgradeFirmware: 407;
253
+ /**
254
+ * Call method not supported, is deprecated
255
+ * @params: { current: string, deprecated: string }
256
+ */
110
257
  readonly CallMethodDeprecated: 408;
258
+ /**
259
+ * Only one device can be connected during firmware upgrade
260
+ */
111
261
  readonly FirmwareUpdateLimitOneDevice: 409;
262
+ /**
263
+ * You need to manually enter boot
264
+ */
112
265
  readonly FirmwareUpdateManuallyEnterBoot: 410;
266
+ /**
267
+ * Manual entry fails. You must manually enter the boot
268
+ */
113
269
  readonly FirmwareUpdateAutoEnterBootFailure: 411;
270
+ /**
271
+ * The new firmware has not been released yet
272
+ */
114
273
  readonly NewFirmwareUnRelease: 412;
274
+ /**
275
+ * use OneKey desktop client to update the firmware
276
+ * because need copy resource file to Touch
277
+ */
115
278
  readonly UseDesktopToUpdateFirmware: 413;
279
+ /**
280
+ * Mandatory firmware update
281
+ * @params:{ connectId: string? , deviceId: string? }
282
+ */
116
283
  readonly NewFirmwareForceUpdate: 414;
284
+ /**
285
+ * Device not support this method
286
+ */
117
287
  readonly DeviceNotSupportMethod: 415;
288
+ /**
289
+ * Forbidden key path
290
+ */
118
291
  readonly ForbiddenKeyPath: 416;
292
+ /**
293
+ * Repeat unlocking
294
+ * all network get address by loop need repeat unlocking
295
+ */
119
296
  readonly RepeatUnlocking: 417;
297
+ /**
298
+ * Defective firmware detected
299
+ */
120
300
  readonly DefectiveFirmware: 418;
301
+ /**
302
+ * Netword request error
303
+ */
121
304
  readonly NetworkError: 500;
305
+ /**
306
+ * Transport not configured
307
+ */
122
308
  readonly TransportNotConfigured: 600;
309
+ /**
310
+ * Transport call in progress
311
+ */
123
312
  readonly TransportCallInProgress: 601;
313
+ /**
314
+ * Transport not found
315
+ */
124
316
  readonly TransportNotFound: 602;
317
+ /**
318
+ * Transport invalid protobuf
319
+ */
125
320
  readonly TransportInvalidProtobuf: 603;
321
+ /**
322
+ * Bluetooth error code
323
+ */
126
324
  readonly BleScanError: 700;
127
325
  readonly BlePermissionError: 701;
128
326
  readonly BleLocationError: 702;
@@ -146,38 +344,145 @@ declare const HardwareErrorCode: {
146
344
  readonly BleDeviceDisconnected: 720;
147
345
  readonly BlePoweredOff: 721;
148
346
  readonly BleUnsupported: 722;
347
+ readonly BleUnavailableWhileUsbConnected: 723;
348
+ /**
349
+ * Hardware runtiome errors
350
+ */
149
351
  readonly RuntimeError: 800;
352
+ /**
353
+ * invalid pin
354
+ */
150
355
  readonly PinInvalid: 801;
356
+ /**
357
+ * pin cancelled by user
358
+ */
151
359
  readonly PinCancelled: 802;
360
+ /**
361
+ * Action cancelled by user
362
+ */
152
363
  readonly ActionCancelled: 803;
364
+ /**
365
+ * Firmware installation failed
366
+ */
153
367
  readonly FirmwareError: 804;
368
+ /**
369
+ * transport response unexpect error
370
+ */
154
371
  readonly ResponseUnexpectTypeError: 805;
372
+ /**
373
+ * bridge network error
374
+ */
155
375
  readonly BridgeNetworkError: 806;
376
+ /**
377
+ * Bridge network timeout
378
+ */
156
379
  readonly BridgeTimeoutError: 807;
380
+ /**
381
+ * Bridge not installed
382
+ */
157
383
  readonly BridgeNotInstalled: 808;
384
+ /**
385
+ * ensure connect timeout
386
+ */
158
387
  readonly PollingTimeout: 809;
388
+ /**
389
+ * ensure connect stop polling
390
+ */
159
391
  readonly PollingStop: 810;
392
+ /**
393
+ * Device does not open blid sign
394
+ */
160
395
  readonly BlindSignDisabled: 811;
161
396
  readonly UnexpectPassphrase: 812;
397
+ /**
398
+ * NFT file already exists
399
+ */
162
400
  readonly FileAlreadyExists: 813;
401
+ /**
402
+ * check file length error
403
+ */
163
404
  readonly CheckDownloadFileError: 814;
405
+ /**
406
+ * not in signing mode
407
+ */
164
408
  readonly NotInSigningMode: 815;
409
+ /**
410
+ * not in signing mode
411
+ */
165
412
  readonly DataOverload: 816;
413
+ /**
414
+ * device disconnected during action
415
+ */
166
416
  readonly BridgeDeviceDisconnected: 817;
417
+ /**
418
+ * BTC PSBT too many utxos
419
+ * @params:{ count: number }
420
+ */
167
421
  readonly BTCPsbtTooManyUtxos: 818;
422
+ /**
423
+ * EMMC file write firmware error
424
+ */
168
425
  readonly EmmcFileWriteFirmwareError: 819;
426
+ /**
427
+ * Firmware verification failed (e.g., bootloader file verify failed)
428
+ */
169
429
  readonly FirmwareVerificationFailed: 820;
430
+ /**
431
+ * Web bridge coonect needs permission
432
+ */
170
433
  readonly BridgeNeedsPermission: 821;
171
434
  readonly CallQueueActionCancelled: 822;
435
+ /**
436
+ * Firmware downgrade not allowed
437
+ */
172
438
  readonly FirmwareDowngradeNotAllowed: 823;
439
+ /**
440
+ * Cosmos invalid JSON message, Only support Amino msgs.
441
+ */
173
442
  readonly CosmosInvalidJsonMessage: 824;
443
+ /**
444
+ * No setting provided
445
+ */
174
446
  readonly DeviceSettingsNotProvided: 825;
447
+ /**
448
+ * Language not supported
449
+ */
175
450
  readonly DeviceSettingsLanguageNotSupport: 826;
451
+ /**
452
+ * Too many inputs
453
+ * @params: { count?: string }
454
+ */
176
455
  readonly TooManyInputs: 827;
456
+ /**
457
+ * The two PIN entries did not match while setting/changing PIN on device
458
+ */
177
459
  readonly PinMismatch: 828;
178
- readonly DeviceLocked: 829;
460
+ /**
461
+ * Protocol V2 device must be unlocked before the requested operation.
462
+ * @params: { failureCode?: string; subcode?: number; firmwareMessage?: string }
463
+ */
464
+ readonly DeviceLocked: 830;
465
+ /**
466
+ * The cached wallet session is invalid or has expired.
467
+ * @params: { failureCode?: string; subcode?: number; firmwareMessage?: string }
468
+ */
469
+ readonly WalletSessionInvalid: 831;
470
+ /**
471
+ * Pro2 NFT storage has reached its item limit.
472
+ * @params: { count: number; limit: number }
473
+ */
474
+ readonly NftStorageLimitReached: 832;
475
+ /**
476
+ * Lowlevel transport connect error
477
+ */
179
478
  readonly LowlevelTrasnportConnectError: 900;
479
+ /**
480
+ * Web USB or Web Bluetooth device not found or needs permission
481
+ */
180
482
  readonly WebDeviceNotFoundOrNeedsPermission: 901;
483
+ /**
484
+ * Web USB or Web Bluetooth device prompt access error
485
+ */
181
486
  readonly WebDevicePromptAccessError: 902;
182
487
  };
183
488
  declare const HardwareErrorCodeMessage: HardwareErrorCodeMessageMapping;
@@ -249,7 +554,8 @@ declare enum EDeviceType {
249
554
  Mini = "mini",
250
555
  Touch = "touch",
251
556
  Pro = "pro",
252
- Pro2 = "pro2"
557
+ Pro2 = "pro2",
558
+ Neo = "neo"
253
559
  }
254
560
 
255
- 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, createNeedUpgradeFirmwareHardwareError, createNewFirmwareForceUpdateHardwareError, createNewFirmwareUnReleaseHardwareError, isHeaderChunk, isKnownTrezorWebUsbDevice, isOnekeyDevice, serializeError, wait };
561
+ 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, createDefectiveFirmwareError, createDeferred, createDeprecatedHardwareError, createDeviceNotSupportMethodError, createKnownBleUuidAliases, createNeedUpgradeFirmwareHardwareError, createNewFirmwareForceUpdateHardwareError, createNewFirmwareUnReleaseHardwareError, hasOnekeyCommunicationService, inferProtocolHintFromUsbId, isHeaderChunk, isKnownTrezorWebUsbDevice, isOnekeyBluetoothDevice, isOnekeyDevice, isPro2FindMyAdvertisementName, 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,
@@ -164,7 +165,9 @@ const HardwareErrorCode = {
164
165
  DeviceSettingsLanguageNotSupport: 826,
165
166
  TooManyInputs: 827,
166
167
  PinMismatch: 828,
167
- DeviceLocked: 829,
168
+ DeviceLocked: 830,
169
+ WalletSessionInvalid: 831,
170
+ NftStorageLimitReached: 832,
168
171
  LowlevelTrasnportConnectError: 900,
169
172
  WebDeviceNotFoundOrNeedsPermission: 901,
170
173
  WebDevicePromptAccessError: 902,
@@ -240,6 +243,7 @@ const HardwareErrorCodeMessage = {
240
243
  [HardwareErrorCode.BleDeviceDisconnected]: 'Device disconnected',
241
244
  [HardwareErrorCode.BlePoweredOff]: 'Bluetooth is turned off',
242
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.',
243
247
  [HardwareErrorCode.RuntimeError]: 'Runtime error',
244
248
  [HardwareErrorCode.PinInvalid]: 'Pin invalid',
245
249
  [HardwareErrorCode.PinCancelled]: 'Pin cancelled',
@@ -270,6 +274,8 @@ const HardwareErrorCodeMessage = {
270
274
  [HardwareErrorCode.TooManyInputs]: 'Too many inputs',
271
275
  [HardwareErrorCode.PinMismatch]: 'PIN mismatch',
272
276
  [HardwareErrorCode.DeviceLocked]: 'Device locked',
277
+ [HardwareErrorCode.WalletSessionInvalid]: 'Wallet session is invalid or expired',
278
+ [HardwareErrorCode.NftStorageLimitReached]: 'NFT storage limit reached. Remove an NFT from the device and try again.',
273
279
  [HardwareErrorCode.LowlevelTrasnportConnectError]: 'Lowlevel transport connect error',
274
280
  [HardwareErrorCode.WebDeviceNotFoundOrNeedsPermission]: 'Web-USB or Web-Bluetooth device not found or needs permission',
275
281
  [HardwareErrorCode.WebDevicePromptAccessError]: 'Web-USB or Web-Bluetooth device prompt access error',
@@ -393,6 +399,7 @@ const ONEKEY_WEBUSB_FILTER = [
393
399
  { vendorId: 0x1209, productId: 0x4f4b },
394
400
  { vendorId: 0x1209, productId: 0x4f4c },
395
401
  ];
402
+ const ONEKEY_PROTOCOL_V2_USB_IDS = [{ vendorId: 0x1209, productId: 0x4f4c }];
396
403
  const TREZOR_WEBUSB_MANUFACTURER_NAMES = new Set(['trezor', 'trezor company', 'satoshilabs']);
397
404
  const isKnownTrezorWebUsbDevice = (descriptor) => {
398
405
  var _a;
@@ -434,13 +441,20 @@ exports.EOneKeyBleMessageKeys = void 0;
434
441
  EOneKeyBleMessageKeys["NOBLE_BLE_STOP_SCAN"] = "$onekey-noble-ble-stop-scan";
435
442
  EOneKeyBleMessageKeys["NOBLE_BLE_GET_DEVICE"] = "$onekey-noble-ble-get-device";
436
443
  EOneKeyBleMessageKeys["NOBLE_BLE_CONNECT"] = "$onekey-noble-ble-connect";
444
+ EOneKeyBleMessageKeys["NOBLE_BLE_RELEASE"] = "$onekey-noble-ble-release";
437
445
  EOneKeyBleMessageKeys["NOBLE_BLE_DISCONNECT"] = "$onekey-noble-ble-disconnect";
438
446
  EOneKeyBleMessageKeys["NOBLE_BLE_WRITE"] = "$onekey-noble-ble-write";
439
447
  EOneKeyBleMessageKeys["NOBLE_BLE_SUBSCRIBE"] = "$onekey-noble-ble-subscribe";
440
448
  EOneKeyBleMessageKeys["NOBLE_BLE_UNSUBSCRIBE"] = "$onekey-noble-ble-unsubscribe";
441
449
  EOneKeyBleMessageKeys["NOBLE_BLE_NOTIFICATION"] = "$onekey-noble-ble-notification";
450
+ EOneKeyBleMessageKeys["NOBLE_BLE_MTU_CHANGED"] = "$onekey-noble-ble-mtu-changed";
442
451
  EOneKeyBleMessageKeys["NOBLE_BLE_CANCEL_PAIRING"] = "$onekey-noble-ble-cancel-pairing";
443
452
  })(exports.EOneKeyBleMessageKeys || (exports.EOneKeyBleMessageKeys = {}));
453
+ exports.EBleDisconnectReason = void 0;
454
+ (function (EBleDisconnectReason) {
455
+ EBleDisconnectReason["DeviceDisconnected"] = "device-disconnected";
456
+ EBleDisconnectReason["IdleKeepAlive"] = "idle-keep-alive";
457
+ })(exports.EBleDisconnectReason || (exports.EBleDisconnectReason = {}));
444
458
  const ONEKEY_SERVICE_UUID = '00000001-0000-1000-8000-00805f9b34fb';
445
459
  const ONEKEY_WRITE_CHARACTERISTIC_UUID = '00000002-0000-1000-8000-00805f9b34fb';
446
460
  const ONEKEY_NOTIFY_CHARACTERISTIC_UUID = '00000003-0000-1000-8000-00805f9b34fb';
@@ -487,11 +501,120 @@ const isOnekeyDevice = (name, id) => {
487
501
  return true;
488
502
  if (normalizedName.startsWith('touch ') ||
489
503
  normalizedName.startsWith('pro ') ||
490
- normalizedName.startsWith('pro2 ')) {
504
+ normalizedName.startsWith('pro2') ||
505
+ normalizedName.startsWith('neo')) {
506
+ return true;
507
+ }
508
+ const compactName = compactBleName(normalizedName);
509
+ if (PRO2_COMPACT_NAME_PATTERN.test(compactName) || NEO_COMPACT_NAME_PATTERN.test(compactName)) {
491
510
  return true;
492
511
  }
493
512
  return isOneKeyShortName(normalizedName);
494
513
  };
514
+ const inferProtocolHintFromUsbId = (vendorId, productId) => ONEKEY_PROTOCOL_V2_USB_IDS.some(id => id.vendorId === vendorId && id.productId === productId)
515
+ ? 'V2'
516
+ : undefined;
517
+ const resolveOneKeyUsbDevicePath = (device) => {
518
+ var _a, _b, _c, _d;
519
+ const serial = (_a = device.serialNumber) === null || _a === void 0 ? void 0 : _a.trim();
520
+ if (serial)
521
+ return serial;
522
+ if (device.vendorId == null && device.productId == null && !device.productName) {
523
+ return undefined;
524
+ }
525
+ const vendorId = ((_b = device.vendorId) !== null && _b !== void 0 ? _b : 0).toString(16).padStart(4, '0');
526
+ const productId = ((_c = device.productId) !== null && _c !== void 0 ? _c : 0).toString(16).padStart(4, '0');
527
+ const product = ((_d = device.productName) !== null && _d !== void 0 ? _d : 'onekey')
528
+ .trim()
529
+ .toLowerCase()
530
+ .replace(/\s+/g, '-')
531
+ .replace(/[^a-z0-9-]/g, '');
532
+ return `usb-${vendorId}-${productId}-${product || 'onekey'}`;
533
+ };
534
+ const BLUETOOTH_BASE_UUID_SUFFIX = '00001000800000805f9b34fb';
535
+ const normalizeBleUuid = (uuid) => (uuid !== null && uuid !== void 0 ? uuid : '').replace(/-/g, '').toLowerCase();
536
+ const createKnownBleUuidAliases = (uuid) => {
537
+ const normalized = normalizeBleUuid(uuid);
538
+ const aliases = new Set([normalized]);
539
+ if (normalized.length !== 32 || !normalized.endsWith(BLUETOOTH_BASE_UUID_SUFFIX)) {
540
+ return aliases;
541
+ }
542
+ const assignedNumber = normalized.slice(0, 8);
543
+ aliases.add(assignedNumber);
544
+ if (assignedNumber.startsWith('0000')) {
545
+ aliases.add(assignedNumber.slice(4));
546
+ }
547
+ return aliases;
548
+ };
549
+ const matchesKnownBleUuid = (actualUuid, aliases) => aliases.has(normalizeBleUuid(actualUuid));
550
+ const ONEKEY_COMMUNICATION_SERVICE_ALIASES = createKnownBleUuidAliases(ONEKEY_SERVICE_UUID);
551
+ const FIDO_SERVICE_ALIASES = createKnownBleUuidAliases('0000fffd-0000-1000-8000-00805f9b34fb');
552
+ const PRO2_COMPACT_NAME_PATTERN = /^(?:onekey)?pro2[a-f0-9]{4}$/i;
553
+ const NEO_COMPACT_NAME_PATTERN = /^(?:onekey)?neo[a-f0-9]{4}$/i;
554
+ const FIND_MY_COMPACT_SUFFIXES = [
555
+ 'findemy',
556
+ 'findem',
557
+ 'finde',
558
+ 'findmy',
559
+ 'findm',
560
+ 'find',
561
+ 'fin',
562
+ ];
563
+ const COMPLETE_FIND_MY_COMPACT_SUFFIXES = ['findemy', 'findmy'];
564
+ const compactBleName = (value) => Array.from(value)
565
+ .filter(character => character !== '-' && character.trim() !== '')
566
+ .join('')
567
+ .toLowerCase();
568
+ const getFindMyCompactSuffix = (compactName) => FIND_MY_COMPACT_SUFFIXES.find(candidate => compactName.endsWith(candidate));
569
+ const getPro2FindMyBaseLength = (value) => {
570
+ const compactName = compactBleName(value);
571
+ const suffix = getFindMyCompactSuffix(compactName);
572
+ if (!suffix)
573
+ return undefined;
574
+ const compactBaseName = compactName.slice(0, -suffix.length);
575
+ return PRO2_COMPACT_NAME_PATTERN.test(compactBaseName) ? compactBaseName.length : undefined;
576
+ };
577
+ const isPro2FindMyAdvertisementName = (value) => {
578
+ if (!value)
579
+ return false;
580
+ if (getPro2FindMyBaseLength(value) !== undefined)
581
+ return true;
582
+ const compactName = compactBleName(value);
583
+ const suffix = COMPLETE_FIND_MY_COMPACT_SUFFIXES.find(candidate => compactName.endsWith(candidate));
584
+ if (!suffix)
585
+ return false;
586
+ return compactName.slice(0, -suffix.length).includes('pro2');
587
+ };
588
+ const normalizePro2FindMyAdvertisementName = (value) => {
589
+ const baseLength = getPro2FindMyBaseLength(value);
590
+ if (baseLength === undefined)
591
+ return value;
592
+ let compactLength = 0;
593
+ for (let index = 0; index < value.length; index += 1) {
594
+ const character = value[index];
595
+ if (character !== '-' && character.trim() !== '') {
596
+ compactLength += 1;
597
+ if (compactLength === baseLength) {
598
+ return value.slice(0, index + 1).trimEnd();
599
+ }
600
+ }
601
+ }
602
+ return value;
603
+ };
604
+ const hasOnekeyCommunicationService = (serviceUuids) => (serviceUuids !== null && serviceUuids !== void 0 ? serviceUuids : []).some(uuid => matchesKnownBleUuid(uuid, ONEKEY_COMMUNICATION_SERVICE_ALIASES));
605
+ const isOnekeyBluetoothDevice = ({ id, name, localName, serviceUuids, }) => {
606
+ const advertisedServiceUuids = serviceUuids !== null && serviceUuids !== void 0 ? serviceUuids : [];
607
+ if (hasOnekeyCommunicationService(advertisedServiceUuids)) {
608
+ return true;
609
+ }
610
+ if (isPro2FindMyAdvertisementName(name) || isPro2FindMyAdvertisementName(localName)) {
611
+ return false;
612
+ }
613
+ if (advertisedServiceUuids.some(uuid => matchesKnownBleUuid(uuid, FIDO_SERVICE_ALIASES))) {
614
+ return false;
615
+ }
616
+ return isOnekeyDevice(name !== null && name !== void 0 ? name : null, id) || isOnekeyDevice(localName !== null && localName !== void 0 ? localName : null, id);
617
+ };
495
618
 
496
619
  /******************************************************************************
497
620
  Copyright (c) Microsoft Corporation.
@@ -564,6 +687,7 @@ exports.EDeviceType = void 0;
564
687
  EDeviceType["Touch"] = "touch";
565
688
  EDeviceType["Pro"] = "pro";
566
689
  EDeviceType["Pro2"] = "pro2";
690
+ EDeviceType["Neo"] = "neo";
567
691
  })(exports.EDeviceType || (exports.EDeviceType = {}));
568
692
 
569
693
  exports.CreateErrorByMessage = CreateErrorByMessage;
@@ -576,6 +700,7 @@ exports.HardwareError = HardwareError;
576
700
  exports.HardwareErrorCode = HardwareErrorCode;
577
701
  exports.HardwareErrorCodeMessage = HardwareErrorCodeMessage;
578
702
  exports.ONEKEY_NOTIFY_CHARACTERISTIC_UUID = ONEKEY_NOTIFY_CHARACTERISTIC_UUID;
703
+ exports.ONEKEY_PROTOCOL_V2_USB_IDS = ONEKEY_PROTOCOL_V2_USB_IDS;
579
704
  exports.ONEKEY_SERVICE_UUID = ONEKEY_SERVICE_UUID;
580
705
  exports.ONEKEY_WEBUSB_FILTER = ONEKEY_WEBUSB_FILTER;
581
706
  exports.ONEKEY_WRITE_CHARACTERISTIC_UUID = ONEKEY_WRITE_CHARACTERISTIC_UUID;
@@ -584,11 +709,20 @@ exports.createDefectiveFirmwareError = createDefectiveFirmwareError;
584
709
  exports.createDeferred = createDeferred;
585
710
  exports.createDeprecatedHardwareError = createDeprecatedHardwareError;
586
711
  exports.createDeviceNotSupportMethodError = createDeviceNotSupportMethodError;
712
+ exports.createKnownBleUuidAliases = createKnownBleUuidAliases;
587
713
  exports.createNeedUpgradeFirmwareHardwareError = createNeedUpgradeFirmwareHardwareError;
588
714
  exports.createNewFirmwareForceUpdateHardwareError = createNewFirmwareForceUpdateHardwareError;
589
715
  exports.createNewFirmwareUnReleaseHardwareError = createNewFirmwareUnReleaseHardwareError;
716
+ exports.hasOnekeyCommunicationService = hasOnekeyCommunicationService;
717
+ exports.inferProtocolHintFromUsbId = inferProtocolHintFromUsbId;
590
718
  exports.isHeaderChunk = isHeaderChunk;
591
719
  exports.isKnownTrezorWebUsbDevice = isKnownTrezorWebUsbDevice;
720
+ exports.isOnekeyBluetoothDevice = isOnekeyBluetoothDevice;
592
721
  exports.isOnekeyDevice = isOnekeyDevice;
722
+ exports.isPro2FindMyAdvertisementName = isPro2FindMyAdvertisementName;
723
+ exports.matchesKnownBleUuid = matchesKnownBleUuid;
724
+ exports.normalizeBleUuid = normalizeBleUuid;
725
+ exports.normalizePro2FindMyAdvertisementName = normalizePro2FindMyAdvertisementName;
726
+ exports.resolveOneKeyUsbDevicePath = resolveOneKeyUsbDevicePath;
593
727
  exports.serializeError = serializeError;
594
728
  exports.wait = wait;
package/jest.config.js ADDED
@@ -0,0 +1,5 @@
1
+ module.exports = {
2
+ preset: '../../jest.config.js',
3
+ testEnvironment: 'node',
4
+ modulePathIgnorePatterns: ['node_modules', '<rootDir>/dist'],
5
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/hd-shared",
3
- "version": "1.2.0-alpha.16",
3
+ "version": "1.2.0-alpha.161",
4
4
  "description": "Hardware SDK's shared tool library",
5
5
  "keywords": [
6
6
  "Hardware-SDK",
@@ -22,8 +22,9 @@
22
22
  "scripts": {
23
23
  "dev": "rimraf dist && rollup -c ../../build/rollup.config.js -w",
24
24
  "build": "rimraf dist && rollup -c ../../build/rollup.config.js",
25
+ "test": "jest",
25
26
  "lint": "eslint .",
26
27
  "lint:fix": "eslint . --fix"
27
28
  },
28
- "gitHead": "2356d951f63a39a46bc995c2090348a383966175"
29
+ "gitHead": "06316117fc9a7ebaecea1ca583b2d105709361bf"
29
30
  }
@@ -0,0 +1,36 @@
1
+ import {
2
+ HardwareErrorCode,
3
+ HardwareErrorCodeMessage,
4
+ TypedError,
5
+ serializeError,
6
+ } from './HardwareError';
7
+
8
+ describe('HardwareErrorCode compatibility', () => {
9
+ test('preserves published Protocol V2 values while leaving code 829 unused', () => {
10
+ expect(HardwareErrorCode).not.toHaveProperty('KaspaPrevTxIdMismatch');
11
+ expect(HardwareErrorCode.DeviceLocked).toBe(830);
12
+ expect(HardwareErrorCode.WalletSessionInvalid).toBe(831);
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
+ });
36
+ });
@@ -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
@@ -488,7 +489,19 @@ export const HardwareErrorCode = {
488
489
  * Protocol V2 device must be unlocked before the requested operation.
489
490
  * @params: { failureCode?: string; subcode?: number; firmwareMessage?: string }
490
491
  */
491
- DeviceLocked: 829,
492
+ DeviceLocked: 830,
493
+
494
+ /**
495
+ * The cached wallet session is invalid or has expired.
496
+ * @params: { failureCode?: string; subcode?: number; firmwareMessage?: string }
497
+ */
498
+ WalletSessionInvalid: 831,
499
+
500
+ /**
501
+ * Pro2 NFT storage has reached its item limit.
502
+ * @params: { count: number; limit: number }
503
+ */
504
+ NftStorageLimitReached: 832,
492
505
 
493
506
  /**
494
507
  * Lowlevel transport connect error
@@ -607,6 +620,8 @@ export const HardwareErrorCodeMessage: HardwareErrorCodeMessageMapping = {
607
620
  [HardwareErrorCode.BleDeviceDisconnected]: 'Device disconnected',
608
621
  [HardwareErrorCode.BlePoweredOff]: 'Bluetooth is turned off',
609
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.',
610
625
 
611
626
  /**
612
627
  * Runtime Error
@@ -642,6 +657,9 @@ export const HardwareErrorCodeMessage: HardwareErrorCodeMessageMapping = {
642
657
  [HardwareErrorCode.TooManyInputs]: 'Too many inputs',
643
658
  [HardwareErrorCode.PinMismatch]: 'PIN mismatch',
644
659
  [HardwareErrorCode.DeviceLocked]: 'Device locked',
660
+ [HardwareErrorCode.WalletSessionInvalid]: 'Wallet session is invalid or expired',
661
+ [HardwareErrorCode.NftStorageLimitReached]:
662
+ 'NFT storage limit reached. Remove an NFT from the device and try again.',
645
663
 
646
664
  /**
647
665
  * Lowlevel transport
@@ -1,9 +1,24 @@
1
- import { isKnownTrezorWebUsbDevice, isOnekeyDevice } from './constants';
1
+ import {
2
+ createKnownBleUuidAliases,
3
+ hasOnekeyCommunicationService,
4
+ inferProtocolHintFromUsbId,
5
+ isKnownTrezorWebUsbDevice,
6
+ isOnekeyBluetoothDevice,
7
+ isOnekeyDevice,
8
+ isPro2FindMyAdvertisementName,
9
+ matchesKnownBleUuid,
10
+ normalizePro2FindMyAdvertisementName,
11
+ resolveOneKeyUsbDevicePath,
12
+ } from './constants';
2
13
 
3
14
  describe('hardware device identity filters', () => {
4
15
  it('accepts known OneKey BLE names', () => {
5
16
  expect(isOnekeyDevice('Touch A1B2')).toBe(true);
6
17
  expect(isOnekeyDevice('Pro A1B2')).toBe(true);
18
+ expect(isOnekeyDevice('Neo A1B2')).toBe(true);
19
+ expect(isOnekeyDevice('Pro2A1B2')).toBe(true);
20
+ expect(isOnekeyDevice('OneKeyPro2A1B2')).toBe(true);
21
+ expect(isOnekeyDevice('Neo22D8')).toBe(true);
7
22
  expect(isOnekeyDevice('K1234')).toBe(true);
8
23
  expect(isOnekeyDevice('S8')).toBe(true);
9
24
  });
@@ -13,6 +28,145 @@ describe('hardware device identity filters', () => {
13
28
  expect(isOnekeyDevice('Ledger Nano X')).toBe(false);
14
29
  });
15
30
 
31
+ it('does not identify an FFFD-only advertisement as OneKey', () => {
32
+ expect(isOnekeyBluetoothDevice({ name: 'Find My', serviceUuids: ['fffd'] })).toBe(false);
33
+ expect(
34
+ isOnekeyBluetoothDevice({ serviceUuids: ['0000fffd-0000-1000-8000-00805f9b34fb'] })
35
+ ).toBe(false);
36
+ });
37
+
38
+ it('identifies Pro2 communication advertisements independently of their display name', () => {
39
+ expect(
40
+ isOnekeyBluetoothDevice({
41
+ name: 'Pro2 A1B2',
42
+ serviceUuids: ['0001', 'fffd'],
43
+ })
44
+ ).toBe(true);
45
+ expect(
46
+ isOnekeyBluetoothDevice({
47
+ localName: 'Pro2 A1B2 - Find My',
48
+ serviceUuids: ['0001', 'fffd'],
49
+ })
50
+ ).toBe(true);
51
+ expect(
52
+ isOnekeyBluetoothDevice({
53
+ name: 'Pro2 5E9D - Finde My',
54
+ serviceUuids: ['0001', 'fffd'],
55
+ })
56
+ ).toBe(true);
57
+ });
58
+
59
+ it('rejects Pro2 Find My entries when the communication service is absent', () => {
60
+ expect(
61
+ isOnekeyBluetoothDevice({
62
+ name: 'Pro2 A1B2 - Find My',
63
+ })
64
+ ).toBe(false);
65
+ expect(
66
+ isOnekeyBluetoothDevice({
67
+ localName: 'OneKey Pro 2 A1B2 - Find My',
68
+ serviceUuids: [],
69
+ })
70
+ ).toBe(false);
71
+ expect(
72
+ isOnekeyBluetoothDevice({
73
+ name: 'Pro2 5E9D - Finde My',
74
+ serviceUuids: ['fffd'],
75
+ })
76
+ ).toBe(false);
77
+ expect(isOnekeyBluetoothDevice({ name: 'Pro2 - Find My' })).toBe(false);
78
+ expect(isOnekeyBluetoothDevice({ name: 'Pro2 G12Z - Find My' })).toBe(false);
79
+ });
80
+
81
+ it('uses a broad Find My guard without broadening public name normalization', () => {
82
+ expect(isPro2FindMyAdvertisementName('Pro2 Griffin - Find My')).toBe(true);
83
+ expect(isPro2FindMyAdvertisementName('Pro2 Griffin')).toBe(false);
84
+ expect(isPro2FindMyAdvertisementName('Pro2 22D8 - Find My')).toBe(true);
85
+ expect(normalizePro2FindMyAdvertisementName('Pro2 Griffin - Find My')).toBe(
86
+ 'Pro2 Griffin - Find My'
87
+ );
88
+ expect(normalizePro2FindMyAdvertisementName('Pro2 22D8 - Find My')).toBe('Pro2 22D8');
89
+ });
90
+
91
+ it.each([
92
+ ['Pro2 A1B2 - Find My', 'Pro2 A1B2'],
93
+ ['Pro2 5E9D - Finde My', 'Pro2 5E9D'],
94
+ [' OneKey Pro 2 A1B2 Find My ', ' OneKey Pro 2 A1B2'],
95
+ ['OneKey Pro-2 22D8--Find-My', 'OneKey Pro-2 22D8'],
96
+ ['Pro2 22D8FindMy', 'Pro2 22D8'],
97
+ ['Pro2 22D8 - Fin', 'Pro2 22D8'],
98
+ ['Pro2 22D8FindM', 'Pro2 22D8'],
99
+ [`Pro2 22D8${'\t'.repeat(10_000)}Find My`, 'Pro2 22D8'],
100
+ ['Pro2 A1B2', 'Pro2 A1B2'],
101
+ ['Pro2 Griffin', 'Pro2 Griffin'],
102
+ ['Find My', 'Find My'],
103
+ ])('normalizes the public Pro2 advertisement name %s', (name, expected) => {
104
+ expect(normalizePro2FindMyAdvertisementName(name)).toBe(expected);
105
+ });
106
+
107
+ it('keeps OneKey discovery on the communication service', () => {
108
+ expect(
109
+ isOnekeyBluetoothDevice({
110
+ name: 'OneKey Pro 2',
111
+ serviceUuids: ['00000001-0000-1000-8000-00805f9b34fb'],
112
+ })
113
+ ).toBe(true);
114
+ });
115
+
116
+ it('only aliases standard Bluetooth Base UUID representations', () => {
117
+ const aliases = createKnownBleUuidAliases('00000001-0000-1000-8000-00805f9b34fb');
118
+
119
+ expect(matchesKnownBleUuid('0001', aliases)).toBe(true);
120
+ expect(matchesKnownBleUuid('00000001', aliases)).toBe(true);
121
+ expect(matchesKnownBleUuid('abcd0001-1234-5678-9012-abcdefabcdef', aliases)).toBe(false);
122
+ });
123
+
124
+ it('does not treat vendor-specific UUID fragments as communication or FIDO services', () => {
125
+ expect(
126
+ isOnekeyBluetoothDevice({
127
+ name: 'OneKey Pro 2',
128
+ serviceUuids: ['abcdfffd-1234-5678-9012-abcdefabcdef'],
129
+ })
130
+ ).toBe(true);
131
+ expect(
132
+ isOnekeyBluetoothDevice({
133
+ serviceUuids: ['abcd0001-1234-5678-9012-abcdefabcdef'],
134
+ })
135
+ ).toBe(false);
136
+ });
137
+
138
+ it('requires an explicitly advertised communication service for strict discovery', () => {
139
+ expect(hasOnekeyCommunicationService([])).toBe(false);
140
+ expect(hasOnekeyCommunicationService(['0001'])).toBe(true);
141
+ expect(hasOnekeyCommunicationService(['abcd0001-1234-5678-9012-abcdefabcdef'])).toBe(false);
142
+ });
143
+
144
+ it('hints Protocol V2 from the current Pro2/Neo USB ID only', () => {
145
+ expect(inferProtocolHintFromUsbId(0x1209, 0x4f4c)).toBe('V2');
146
+ expect(inferProtocolHintFromUsbId(0x1209, 0x53c1)).toBeUndefined();
147
+ expect(inferProtocolHintFromUsbId(0x1209, 0x4f4a)).toBeUndefined();
148
+ expect(inferProtocolHintFromUsbId(0x1209, 0x4f4b)).toBeUndefined();
149
+ });
150
+
151
+ it('uses the USB serial when present and synthesizes a path when firmware omits it', () => {
152
+ expect(
153
+ resolveOneKeyUsbDevicePath({
154
+ vendorId: 0x1209,
155
+ productId: 0x4f4c,
156
+ productName: 'OneKey Pro 2',
157
+ serialNumber: 'PRO2-SERIAL',
158
+ })
159
+ ).toBe('PRO2-SERIAL');
160
+ expect(
161
+ resolveOneKeyUsbDevicePath({
162
+ vendorId: 0x1209,
163
+ productId: 0x4f4c,
164
+ productName: 'OneKey Neo',
165
+ serialNumber: '',
166
+ })
167
+ ).toBe('usb-1209-4f4c-onekey-neo');
168
+ });
169
+
16
170
  it('only filters WebUSB descriptors that are explicitly identified as Trezor', () => {
17
171
  expect(
18
172
  isKnownTrezorWebUsbDevice({
package/src/constants.ts CHANGED
@@ -10,13 +10,16 @@ export type HardwareConnectProtocol =
10
10
 
11
11
  export const ONEKEY_WEBUSB_FILTER = [
12
12
  { vendorId: 0x1209, productId: 0x53c0 }, // Classic Boot、Classic1s Boot、Mini Boot
13
- { vendorId: 0x1209, productId: 0x53c1 }, // Classic Firmware、Classic1s Firmware、Mini Firmware、Pro Firmware、Touch Firmware、Pro2(旧固件,勿删:存量设备仍以此 PID 枚举)
14
- { vendorId: 0x1209, productId: 0x4f4a }, // Pro Boot、Touch Boot、Pro2
15
- { vendorId: 0x1209, productId: 0x4f4b }, // Pro Firmware、Touch Firmware(Not implemented Trezor)、Pro2
16
- { vendorId: 0x1209, productId: 0x4f4c }, // Pro Board、Pro2(新固件 PID)
13
+ { vendorId: 0x1209, productId: 0x53c1 }, // Classic/Classic1s/Mini/Pro/Touch firmware and legacy Pro2; keep for existing devices
14
+ { vendorId: 0x1209, productId: 0x4f4a }, // Pro bootloader, Touch bootloader, Pro2
15
+ { vendorId: 0x1209, productId: 0x4f4b }, // Pro/Touch firmware (Trezor not implemented), Pro2
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;
@@ -86,14 +89,33 @@ export enum EOneKeyBleMessageKeys {
86
89
  NOBLE_BLE_STOP_SCAN = '$onekey-noble-ble-stop-scan',
87
90
  NOBLE_BLE_GET_DEVICE = '$onekey-noble-ble-get-device',
88
91
  NOBLE_BLE_CONNECT = '$onekey-noble-ble-connect',
92
+ // Logical end-of-operation from the renderer (keep-alive): the physical link
93
+ // stays up but the main process starts its idle-disconnect countdown.
94
+ NOBLE_BLE_RELEASE = '$onekey-noble-ble-release',
89
95
  NOBLE_BLE_DISCONNECT = '$onekey-noble-ble-disconnect',
90
96
  NOBLE_BLE_WRITE = '$onekey-noble-ble-write',
91
97
  NOBLE_BLE_SUBSCRIBE = '$onekey-noble-ble-subscribe',
92
98
  NOBLE_BLE_UNSUBSCRIBE = '$onekey-noble-ble-unsubscribe',
93
99
  NOBLE_BLE_NOTIFICATION = '$onekey-noble-ble-notification',
100
+ NOBLE_BLE_MTU_CHANGED = '$onekey-noble-ble-mtu-changed',
94
101
  NOBLE_BLE_CANCEL_PAIRING = '$onekey-noble-ble-cancel-pairing',
95
102
  }
96
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
+
97
119
  export const ONEKEY_SERVICE_UUID = '00000001-0000-1000-8000-00805f9b34fb';
98
120
  export const ONEKEY_WRITE_CHARACTERISTIC_UUID = '00000002-0000-1000-8000-00805f9b34fb';
99
121
  export const ONEKEY_NOTIFY_CHARACTERISTIC_UUID = '00000003-0000-1000-8000-00805f9b34fb';
@@ -148,9 +170,170 @@ export const isOnekeyDevice = (name: string | null, id?: string): boolean => {
148
170
  if (
149
171
  normalizedName.startsWith('touch ') ||
150
172
  normalizedName.startsWith('pro ') ||
151
- normalizedName.startsWith('pro2 ')
173
+ normalizedName.startsWith('pro2') ||
174
+ normalizedName.startsWith('neo')
152
175
  ) {
153
176
  return true;
154
177
  }
178
+ const compactName = compactBleName(normalizedName);
179
+ if (PRO2_COMPACT_NAME_PATTERN.test(compactName) || NEO_COMPACT_NAME_PATTERN.test(compactName)) {
180
+ return true;
181
+ }
155
182
  return isOneKeyShortName(normalizedName);
156
183
  };
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
+
214
+ type BluetoothDeviceIdentity = {
215
+ id?: string;
216
+ name?: string | null;
217
+ localName?: string | null;
218
+ serviceUuids?: Array<string | null | undefined> | null;
219
+ };
220
+
221
+ const BLUETOOTH_BASE_UUID_SUFFIX = '00001000800000805f9b34fb';
222
+
223
+ export const normalizeBleUuid = (uuid?: string | null) =>
224
+ (uuid ?? '').replace(/-/g, '').toLowerCase();
225
+
226
+ export const createKnownBleUuidAliases = (uuid: string): ReadonlySet<string> => {
227
+ const normalized = normalizeBleUuid(uuid);
228
+ const aliases = new Set([normalized]);
229
+
230
+ if (normalized.length !== 32 || !normalized.endsWith(BLUETOOTH_BASE_UUID_SUFFIX)) {
231
+ return aliases;
232
+ }
233
+
234
+ const assignedNumber = normalized.slice(0, 8);
235
+ aliases.add(assignedNumber);
236
+ if (assignedNumber.startsWith('0000')) {
237
+ aliases.add(assignedNumber.slice(4));
238
+ }
239
+ return aliases;
240
+ };
241
+
242
+ export const matchesKnownBleUuid = (
243
+ actualUuid: string | null | undefined,
244
+ aliases: ReadonlySet<string>
245
+ ) => aliases.has(normalizeBleUuid(actualUuid));
246
+
247
+ const ONEKEY_COMMUNICATION_SERVICE_ALIASES = createKnownBleUuidAliases(ONEKEY_SERVICE_UUID);
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
+ };
279
+
280
+ export const isPro2FindMyAdvertisementName = (value?: string | null) => {
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
+ export const hasOnekeyCommunicationService = (
311
+ serviceUuids: Array<string | null | undefined> | null | undefined
312
+ ) =>
313
+ (serviceUuids ?? []).some(uuid =>
314
+ matchesKnownBleUuid(uuid, ONEKEY_COMMUNICATION_SERVICE_ALIASES)
315
+ );
316
+
317
+ export const isOnekeyBluetoothDevice = ({
318
+ id,
319
+ name,
320
+ localName,
321
+ serviceUuids,
322
+ }: BluetoothDeviceIdentity): boolean => {
323
+ const advertisedServiceUuids = serviceUuids ?? [];
324
+ if (hasOnekeyCommunicationService(advertisedServiceUuids)) {
325
+ return true;
326
+ }
327
+
328
+ // Android can return a connected Find My peripheral without its advertised
329
+ // services. Do not let the Pro2-looking name fall through to name discovery.
330
+ if (isPro2FindMyAdvertisementName(name) || isPro2FindMyAdvertisementName(localName)) {
331
+ return false;
332
+ }
333
+
334
+ if (advertisedServiceUuids.some(uuid => matchesKnownBleUuid(uuid, FIDO_SERVICE_ALIASES))) {
335
+ return false;
336
+ }
337
+
338
+ return isOnekeyDevice(name ?? null, id) || isOnekeyDevice(localName ?? null, id);
339
+ };
package/src/deviceType.ts CHANGED
@@ -7,4 +7,5 @@ export enum EDeviceType {
7
7
  Touch = 'touch',
8
8
  Pro = 'pro',
9
9
  Pro2 = 'pro2',
10
+ Neo = 'neo',
10
11
  }