@onekeyfe/hd-core 1.2.0-alpha.14 → 1.2.0-alpha.16

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.
@@ -1,6 +1,7 @@
1
1
  import { HardwareErrorCode } from '@onekeyfe/hd-shared';
2
2
 
3
3
  import { DeviceCommands } from '../src/device/DeviceCommands';
4
+ import { DEVICE } from '../src/events';
4
5
 
5
6
  jest.mock('../src/data/config', () => ({
6
7
  getSDKVersion: jest.fn(() => '1.0.0'),
@@ -169,3 +170,79 @@ describe('DeviceCommands failure mapping', () => {
169
170
  });
170
171
  });
171
172
  });
173
+
174
+ describe('DeviceCommands Protocol V2 interactive response compatibility', () => {
175
+ it('still auto-acks ButtonRequest when no hardware UI listener is registered', async () => {
176
+ const commands = createCommands();
177
+ commands.device = {
178
+ ...commands.device,
179
+ getCurrentDeviceType: jest.fn(() => 'pro2'),
180
+ setCancelableAction: jest.fn(),
181
+ emit: jest.fn(),
182
+ listenerCount: jest.fn(() => 0),
183
+ } as any;
184
+ commands._commonCall = jest.fn().mockResolvedValue({
185
+ type: 'Success',
186
+ message: {},
187
+ }) as any;
188
+
189
+ await expect(
190
+ commands._filterCommonTypes(
191
+ {
192
+ type: 'ButtonRequest',
193
+ message: { code: 'ButtonRequest_PinEntry' },
194
+ } as any,
195
+ 'GetAddress'
196
+ )
197
+ ).resolves.toMatchObject({ type: 'Success' });
198
+
199
+ expect(commands.device.emit).toHaveBeenCalledWith(
200
+ DEVICE.BUTTON,
201
+ commands.device,
202
+ expect.objectContaining({ code: 'ButtonRequest_PinEntry' })
203
+ );
204
+ expect(commands._commonCall).toHaveBeenCalledWith('ButtonAck', {}, undefined);
205
+ });
206
+
207
+ it('rejects PassphraseRequest when the Pro2 UI listener is not registered', async () => {
208
+ const commands = createCommands();
209
+ commands.device = {
210
+ ...commands.device,
211
+ listenerCount: jest.fn(() => 0),
212
+ } as any;
213
+
214
+ await expect(
215
+ commands._filterCommonTypes(
216
+ {
217
+ type: 'PassphraseRequest',
218
+ message: { exists_attach_pin_user: true },
219
+ } as any,
220
+ 'GetAddress'
221
+ )
222
+ ).rejects.toMatchObject({
223
+ errorCode: HardwareErrorCode.RuntimeError,
224
+ message: '_promptPassphrase: Passphrase callback not configured',
225
+ });
226
+ });
227
+
228
+ it('rejects PinMatrixRequest when the Pro2 UI listener is not registered', async () => {
229
+ const commands = createCommands();
230
+ commands.device = {
231
+ ...commands.device,
232
+ instanceId: 'pro2-test-device',
233
+ listenerCount: jest.fn(() => 0),
234
+ } as any;
235
+
236
+ await expect(
237
+ commands._filterCommonTypes(
238
+ {
239
+ type: 'PinMatrixRequest',
240
+ message: { type: 'PinMatrixRequestType_Current' },
241
+ } as any,
242
+ 'GetAddress'
243
+ )
244
+ ).rejects.toMatchObject({
245
+ errorCode: HardwareErrorCode.RuntimeError,
246
+ });
247
+ });
248
+ });
@@ -0,0 +1,40 @@
1
+ import { DEVICE } from '../src/events';
2
+ import { registerHardwareUiEventListeners } from '../src/core/deviceEventRegistration';
3
+
4
+ const handlers = {
5
+ pin: jest.fn(),
6
+ button: jest.fn(),
7
+ passphrase: jest.fn(),
8
+ passphraseOnDevice: jest.fn(),
9
+ };
10
+
11
+ const createDevice = (protocolV2: boolean) => ({
12
+ isProtocolV2: jest.fn(() => protocolV2),
13
+ on: jest.fn(),
14
+ });
15
+
16
+ describe('hardware UI event registration', () => {
17
+ test('keeps all interactive UI events for Protocol V2 devices during compatibility mode', () => {
18
+ const device = createDevice(true);
19
+
20
+ expect(registerHardwareUiEventListeners(device as any, handlers)).toBe(true);
21
+ expect(device.on.mock.calls.map(([type]) => type)).toEqual([
22
+ DEVICE.PIN,
23
+ DEVICE.BUTTON,
24
+ DEVICE.PASSPHRASE,
25
+ DEVICE.PASSPHRASE_ON_DEVICE,
26
+ ]);
27
+ });
28
+
29
+ test('keeps the existing interactive event listeners for Protocol V1 devices', () => {
30
+ const device = createDevice(false);
31
+
32
+ expect(registerHardwareUiEventListeners(device as any, handlers)).toBe(true);
33
+ expect(device.on.mock.calls.map(([type]) => type)).toEqual([
34
+ DEVICE.PIN,
35
+ DEVICE.BUTTON,
36
+ DEVICE.PASSPHRASE,
37
+ DEVICE.PASSPHRASE_ON_DEVICE,
38
+ ]);
39
+ });
40
+ });
@@ -0,0 +1,10 @@
1
+ import { DEVICE } from '../events';
2
+ import type { Device, DeviceEvents } from '../device/Device';
3
+ export type HardwareUiEventHandlers = {
4
+ pin: (...event: DeviceEvents[typeof DEVICE.PIN]) => void;
5
+ button: (...event: DeviceEvents[typeof DEVICE.BUTTON]) => void;
6
+ passphrase: (...event: DeviceEvents[typeof DEVICE.PASSPHRASE]) => void;
7
+ passphraseOnDevice: (...event: DeviceEvents[typeof DEVICE.PASSPHRASE_ON_DEVICE]) => void;
8
+ };
9
+ export declare function registerHardwareUiEventListeners(device: Pick<Device, 'on'>, handlers: HardwareUiEventHandlers): boolean;
10
+ //# sourceMappingURL=deviceEventRegistration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deviceEventRegistration.d.ts","sourceRoot":"","sources":["../../src/core/deviceEventRegistration.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAEnC,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAE7D,MAAM,MAAM,uBAAuB,GAAG;IACpC,GAAG,EAAE,CAAC,GAAG,KAAK,EAAE,YAAY,CAAC,OAAO,MAAM,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC;IACzD,MAAM,EAAE,CAAC,GAAG,KAAK,EAAE,YAAY,CAAC,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;IAC/D,UAAU,EAAE,CAAC,GAAG,KAAK,EAAE,YAAY,CAAC,OAAO,MAAM,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC;IACvE,kBAAkB,EAAE,CAAC,GAAG,KAAK,EAAE,YAAY,CAAC,OAAO,MAAM,CAAC,oBAAoB,CAAC,KAAK,IAAI,CAAC;CAC1F,CAAC;AAEF,wBAAgB,gCAAgC,CAC9C,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,EAC1B,QAAQ,EAAE,uBAAuB,WAOlC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":";AACA,OAAO,YAAY,MAAM,QAAQ,CAAC;AAoClC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAkB1C,OAAO,eAAe,MAAM,2BAA2B,CAAC;AAKxD,OAAO,KAAK,EAAE,eAAe,EAAyB,MAAM,UAAU,CAAC;AACvE,OAAO,KAAK,EAAE,WAAW,EAAmD,MAAM,WAAW,CAAC;AAI9F,OAAO,KAAK,EAAE,6BAA6B,EAAoB,MAAM,wBAAwB,CAAC;AAW9F,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;AA+D7D,eAAO,MAAM,OAAO,YAAmB,WAAW,WAAW,WAAW,iBA6EvE,CAAC;AAyzBF,eAAO,MAAM,MAAM,YAAa,WAAW,cAAc,MAAM,SAkF9D,CAAC;AAiFF,eAAO,MAAM,qBAAqB,gFAejC,CAAC;AA0GF,MAAM,CAAC,OAAO,OAAO,IAAK,SAAQ,YAAY;IAC5C,OAAO,CAAC,cAAc,CAAoB;IAE1C,SAAgB,aAAa,EAAE,MAAM,CAAC;IAEtC,OAAO,CAAC,YAAY,CAAsB;IAG1C,OAAO,CAAC,qBAAqB,CAA4B;IAEzD,OAAO,CAAC,iBAAiB,CAAoB;;IAS7C,eAAe,CAAC,WAAW,EAAE,MAAM;IAInC,OAAO,CAAC,cAAc;IAoBhB,aAAa,CAAC,OAAO,EAAE,WAAW;IA+DxC,OAAO;CASR;AAED,eAAO,MAAM,QAAQ,YAGpB,CAAC;AAEF,eAAO,MAAM,aAAa,uBAIzB,CAAC;AAMF,eAAO,MAAM,IAAI,aACL,eAAe,aACd,GAAG,WACL,6BAA6B,8BAoBvC,CAAC;AAEF,eAAO,MAAM,eAAe;SAKrB,eAAe,CAAC,KAAK,CAAC;eAChB,GAAG;;UASf,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":";AACA,OAAO,YAAY,MAAM,QAAQ,CAAC;AAoClC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAkB1C,OAAO,eAAe,MAAM,2BAA2B,CAAC;AAMxD,OAAO,KAAK,EAAE,eAAe,EAAyB,MAAM,UAAU,CAAC;AACvE,OAAO,KAAK,EAAE,WAAW,EAAmD,MAAM,WAAW,CAAC;AAI9F,OAAO,KAAK,EAAE,6BAA6B,EAAoB,MAAM,wBAAwB,CAAC;AAW9F,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;AA+D7D,eAAO,MAAM,OAAO,YAAmB,WAAW,WAAW,WAAW,iBA6EvE,CAAC;AA0zBF,eAAO,MAAM,MAAM,YAAa,WAAW,cAAc,MAAM,SAkF9D,CAAC;AAiFF,eAAO,MAAM,qBAAqB,gFAejC,CAAC;AA0GF,MAAM,CAAC,OAAO,OAAO,IAAK,SAAQ,YAAY;IAC5C,OAAO,CAAC,cAAc,CAAoB;IAE1C,SAAgB,aAAa,EAAE,MAAM,CAAC;IAEtC,OAAO,CAAC,YAAY,CAAsB;IAG1C,OAAO,CAAC,qBAAqB,CAA4B;IAEzD,OAAO,CAAC,iBAAiB,CAAoB;;IAS7C,eAAe,CAAC,WAAW,EAAE,MAAM;IAInC,OAAO,CAAC,cAAc;IAoBhB,aAAa,CAAC,OAAO,EAAE,WAAW;IA+DxC,OAAO;CASR;AAED,eAAO,MAAM,QAAQ,YAGpB,CAAC;AAEF,eAAO,MAAM,aAAa,uBAIzB,CAAC;AAMF,eAAO,MAAM,IAAI,aACL,eAAe,aACd,GAAG,WACL,6BAA6B,8BAoBvC,CAAC;AAEF,eAAO,MAAM,eAAe;SAKrB,eAAe,CAAC,KAAK,CAAC;eAChB,GAAG;;UASf,CAAC"}
package/dist/index.js CHANGED
@@ -58169,6 +58169,14 @@ class RequestQueue {
58169
58169
  }
58170
58170
  }
58171
58171
 
58172
+ function registerHardwareUiEventListeners(device, handlers) {
58173
+ device.on(DEVICE.PIN, handlers.pin);
58174
+ device.on(DEVICE.BUTTON, handlers.button);
58175
+ device.on(DEVICE.PASSPHRASE, handlers.passphrase);
58176
+ device.on(DEVICE.PASSPHRASE_ON_DEVICE, handlers.passphraseOnDevice);
58177
+ return true;
58178
+ }
58179
+
58172
58180
  const getMutex = () => {
58173
58181
  const DEFAULT_ID = Symbol();
58174
58182
  const locks = {};
@@ -58445,10 +58453,14 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
58445
58453
  if (activeRequests.length > 0) {
58446
58454
  Log.warn(`[${method.instanceId}] Device ${device.instanceId} has ${activeRequests.length} active requests:`, activeRequests.map(formatRequestContext));
58447
58455
  }
58448
- device.on(DEVICE.PIN, onDevicePinHandler);
58449
- device.on(DEVICE.BUTTON, onDeviceButtonHandler);
58450
- device.on(DEVICE.PASSPHRASE, message.payload.useEmptyPassphrase ? onEmptyPassphraseHandler : onDevicePassphraseHandler);
58451
- device.on(DEVICE.PASSPHRASE_ON_DEVICE, onEnterPassphraseOnDeviceHandler);
58456
+ registerHardwareUiEventListeners(device, {
58457
+ pin: onDevicePinHandler,
58458
+ button: onDeviceButtonHandler,
58459
+ passphrase: message.payload.useEmptyPassphrase
58460
+ ? onEmptyPassphraseHandler
58461
+ : onDevicePassphraseHandler,
58462
+ passphraseOnDevice: onEnterPassphraseOnDeviceHandler,
58463
+ });
58452
58464
  device.on(DEVICE.FEATURES, onDeviceFeaturesHandler);
58453
58465
  device.on(DEVICE.SELECT_DEVICE_IN_BOOTLOADER_FOR_WEB_DEVICE, onSelectDeviceInBootloaderForWebDeviceHandler);
58454
58466
  device.on(DEVICE.SELECT_DEVICE_FOR_SWITCH_FIRMWARE_WEB_DEVICE, onSelectDeviceForSwitchFirmwareWebDeviceHandler);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/hd-core",
3
- "version": "1.2.0-alpha.14",
3
+ "version": "1.2.0-alpha.16",
4
4
  "description": "Core processes and APIs for communicating with OneKey hardware devices.",
5
5
  "author": "OneKey",
6
6
  "homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
@@ -25,8 +25,8 @@
25
25
  "url": "https://github.com/OneKeyHQ/hardware-js-sdk/issues"
26
26
  },
27
27
  "dependencies": {
28
- "@onekeyfe/hd-shared": "1.2.0-alpha.14",
29
- "@onekeyfe/hd-transport": "1.2.0-alpha.14",
28
+ "@onekeyfe/hd-shared": "1.2.0-alpha.16",
29
+ "@onekeyfe/hd-transport": "1.2.0-alpha.16",
30
30
  "axios": "1.15.2",
31
31
  "bignumber.js": "^9.0.2",
32
32
  "bytebuffer": "^5.0.1",
@@ -44,5 +44,5 @@
44
44
  "@types/w3c-web-usb": "^1.0.10",
45
45
  "@types/web-bluetooth": "^0.0.21"
46
46
  },
47
- "gitHead": "c1edaed6435fb6049c7516c64b298ee62519e797"
47
+ "gitHead": "2356d951f63a39a46bc995c2090348a383966175"
48
48
  }
@@ -0,0 +1,21 @@
1
+ import { DEVICE } from '../events';
2
+
3
+ import type { Device, DeviceEvents } from '../device/Device';
4
+
5
+ export type HardwareUiEventHandlers = {
6
+ pin: (...event: DeviceEvents[typeof DEVICE.PIN]) => void;
7
+ button: (...event: DeviceEvents[typeof DEVICE.BUTTON]) => void;
8
+ passphrase: (...event: DeviceEvents[typeof DEVICE.PASSPHRASE]) => void;
9
+ passphraseOnDevice: (...event: DeviceEvents[typeof DEVICE.PASSPHRASE_ON_DEVICE]) => void;
10
+ };
11
+
12
+ export function registerHardwareUiEventListeners(
13
+ device: Pick<Device, 'on'>,
14
+ handlers: HardwareUiEventHandlers
15
+ ) {
16
+ device.on(DEVICE.PIN, handlers.pin);
17
+ device.on(DEVICE.BUTTON, handlers.button);
18
+ device.on(DEVICE.PASSPHRASE, handlers.passphrase);
19
+ device.on(DEVICE.PASSPHRASE_ON_DEVICE, handlers.passphraseOnDevice);
20
+ return true;
21
+ }
package/src/core/index.ts CHANGED
@@ -55,6 +55,7 @@ import {
55
55
  import TransportManager from '../data-manager/TransportManager';
56
56
  import DeviceConnector from '../device/DeviceConnector';
57
57
  import RequestQueue from './RequestQueue';
58
+ import { registerHardwareUiEventListeners } from './deviceEventRegistration';
58
59
  import { getSynchronize } from '../utils/getSynchronize';
59
60
  import { runMethodWithUnlockRetry } from '../protocols/protocol-v2/unlockRetry';
60
61
 
@@ -395,13 +396,14 @@ const onCallDevice = async (
395
396
  );
396
397
  }
397
398
 
398
- device.on(DEVICE.PIN, onDevicePinHandler);
399
- device.on(DEVICE.BUTTON, onDeviceButtonHandler);
400
- device.on(
401
- DEVICE.PASSPHRASE,
402
- message.payload.useEmptyPassphrase ? onEmptyPassphraseHandler : onDevicePassphraseHandler
403
- );
404
- device.on(DEVICE.PASSPHRASE_ON_DEVICE, onEnterPassphraseOnDeviceHandler);
399
+ registerHardwareUiEventListeners(device, {
400
+ pin: onDevicePinHandler,
401
+ button: onDeviceButtonHandler,
402
+ passphrase: message.payload.useEmptyPassphrase
403
+ ? onEmptyPassphraseHandler
404
+ : onDevicePassphraseHandler,
405
+ passphraseOnDevice: onEnterPassphraseOnDeviceHandler,
406
+ });
405
407
  device.on(DEVICE.FEATURES, onDeviceFeaturesHandler);
406
408
  device.on(
407
409
  DEVICE.SELECT_DEVICE_IN_BOOTLOADER_FOR_WEB_DEVICE,