@onekeyfe/hd-core 1.2.0-alpha.22 → 1.2.0-alpha.24

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.
Files changed (151) hide show
  1. package/__tests__/DeviceCommands.test.ts +43 -8
  2. package/__tests__/connectSettings.test.ts +5 -47
  3. package/__tests__/device-lifecycle-events.test.ts +59 -0
  4. package/__tests__/device-settings.test.ts +1 -1
  5. package/__tests__/device-wallet-session-store.test.ts +41 -0
  6. package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +30 -39
  7. package/__tests__/logBlockEvent.test.ts +17 -0
  8. package/__tests__/open-wallet-session.test.ts +233 -111
  9. package/__tests__/protocol-v2-ping.test.ts +28 -0
  10. package/__tests__/protocol-v2.test.ts +513 -313
  11. package/__tests__/public-pro2-api-boundary.test.ts +22 -0
  12. package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
  13. package/dist/api/FirmwareUpdateV2.d.ts +0 -11
  14. package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
  15. package/dist/api/FirmwareUpdateV3.d.ts +3 -7
  16. package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
  17. package/dist/api/FirmwareUpdateV4.d.ts +5 -21
  18. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  19. package/dist/api/GetPassphraseState.d.ts.map +1 -1
  20. package/dist/api/OpenWalletSession.d.ts +1 -8
  21. package/dist/api/OpenWalletSession.d.ts.map +1 -1
  22. package/dist/api/device/DeviceUpdateBootloader.d.ts +1 -5
  23. package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
  24. package/dist/api/device/DeviceWipe.d.ts.map +1 -1
  25. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +0 -7
  26. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
  27. package/dist/api/firmware/getBinary.d.ts +0 -7
  28. package/dist/api/firmware/getBinary.d.ts.map +1 -1
  29. package/dist/api/firmware/updateBootloader.d.ts +0 -2
  30. package/dist/api/firmware/updateBootloader.d.ts.map +1 -1
  31. package/dist/api/firmware/uploadFirmware.d.ts +1 -9
  32. package/dist/api/firmware/uploadFirmware.d.ts.map +1 -1
  33. package/dist/api/index.d.ts +1 -0
  34. package/dist/api/index.d.ts.map +1 -1
  35. package/dist/api/protocol-v2/Ping.d.ts +2 -0
  36. package/dist/api/protocol-v2/Ping.d.ts.map +1 -1
  37. package/dist/api/stellar/StellarSignTransaction.d.ts +1 -1
  38. package/dist/core/index.d.ts.map +1 -1
  39. package/dist/data-manager/DataManager.d.ts +0 -1
  40. package/dist/data-manager/DataManager.d.ts.map +1 -1
  41. package/dist/data-manager/connectSettings.d.ts.map +1 -1
  42. package/dist/device/Device.d.ts +3 -2
  43. package/dist/device/Device.d.ts.map +1 -1
  44. package/dist/device/DeviceCommands.d.ts.map +1 -1
  45. package/dist/events/device.d.ts +1 -0
  46. package/dist/events/device.d.ts.map +1 -1
  47. package/dist/events/logBlockEvent.d.ts.map +1 -1
  48. package/dist/events/ui-request.d.ts +1 -0
  49. package/dist/events/ui-request.d.ts.map +1 -1
  50. package/dist/index.d.ts +98 -278
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/index.js +876 -2647
  53. package/dist/inject.d.ts.map +1 -1
  54. package/dist/lowLevelInject.d.ts.map +1 -1
  55. package/dist/protocols/protocol-v2/settingsUnlockPolicy.d.ts.map +1 -1
  56. package/dist/protocols/protocol-v2/unlockRetry.d.ts +2 -3
  57. package/dist/protocols/protocol-v2/unlockRetry.d.ts.map +1 -1
  58. package/dist/protocols/protocol-v2/walletSession.d.ts +12 -0
  59. package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
  60. package/dist/topLevelInject.d.ts.map +1 -1
  61. package/dist/types/api/checkAllFirmwareRelease.d.ts +0 -3
  62. package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
  63. package/dist/types/api/deviceUpdateBootloader.d.ts +0 -6
  64. package/dist/types/api/deviceUpdateBootloader.d.ts.map +1 -1
  65. package/dist/types/api/export.d.ts +1 -4
  66. package/dist/types/api/export.d.ts.map +1 -1
  67. package/dist/types/api/firmwareUpdate.d.ts +0 -69
  68. package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
  69. package/dist/types/api/getPassphraseState.d.ts.map +1 -1
  70. package/dist/types/api/index.d.ts +4 -10
  71. package/dist/types/api/index.d.ts.map +1 -1
  72. package/dist/types/api/openWalletSession.d.ts +0 -12
  73. package/dist/types/api/openWalletSession.d.ts.map +1 -1
  74. package/dist/types/api/protocolV2.d.ts +4 -0
  75. package/dist/types/api/protocolV2.d.ts.map +1 -1
  76. package/dist/types/settings.d.ts +0 -13
  77. package/dist/types/settings.d.ts.map +1 -1
  78. package/dist/utils/deviceInfoUtils.d.ts.map +1 -1
  79. package/dist/utils/patch.d.ts +1 -1
  80. package/dist/utils/patch.d.ts.map +1 -1
  81. package/package.json +4 -4
  82. package/src/api/CheckAllFirmwareRelease.ts +3 -16
  83. package/src/api/FirmwareUpdateV2.ts +119 -284
  84. package/src/api/FirmwareUpdateV3.ts +55 -248
  85. package/src/api/FirmwareUpdateV4.ts +293 -751
  86. package/src/api/GetPassphraseState.ts +11 -5
  87. package/src/api/OpenWalletSession.ts +23 -86
  88. package/src/api/device/DeviceUpdateBootloader.ts +6 -114
  89. package/src/api/device/DeviceWipe.ts +2 -0
  90. package/src/api/firmware/FirmwareUpdateBaseMethod.ts +0 -50
  91. package/src/api/firmware/updateBootloader.ts +4 -19
  92. package/src/api/firmware/uploadFirmware.ts +22 -140
  93. package/src/api/index.ts +1 -0
  94. package/src/api/protocol-v2/Ping.ts +32 -1
  95. package/src/core/index.ts +40 -7
  96. package/src/data/messages/messages-protocol-v2.json +49 -56
  97. package/src/data-manager/DataManager.ts +33 -33
  98. package/src/data-manager/connectSettings.ts +0 -11
  99. package/src/device/Device.ts +29 -8
  100. package/src/device/DeviceCommands.ts +43 -151
  101. package/src/events/device.ts +1 -0
  102. package/src/events/logBlockEvent.ts +1 -15
  103. package/src/events/ui-request.ts +1 -0
  104. package/src/index.ts +0 -5
  105. package/src/inject.ts +4 -22
  106. package/src/lowLevelInject.ts +1 -5
  107. package/src/protocols/protocol-v2/deviceSession.ts +1 -1
  108. package/src/protocols/protocol-v2/settingsUnlockPolicy.ts +0 -1
  109. package/src/protocols/protocol-v2/unlockRetry.ts +20 -3
  110. package/src/protocols/protocol-v2/walletSession.ts +57 -18
  111. package/src/topLevelInject.ts +1 -5
  112. package/src/types/api/checkAllFirmwareRelease.ts +0 -3
  113. package/src/types/api/deviceUpdateBootloader.ts +0 -6
  114. package/src/types/api/export.ts +0 -18
  115. package/src/types/api/firmwareUpdate.ts +0 -76
  116. package/src/types/api/getPassphraseState.ts +4 -3
  117. package/src/types/api/index.ts +3 -14
  118. package/src/types/api/openWalletSession.ts +0 -19
  119. package/src/types/api/protocolV2.ts +10 -0
  120. package/src/types/settings.ts +0 -13
  121. package/src/utils/deviceInfoUtils.ts +2 -3
  122. package/__tests__/firmware-update/firmware-artifact-source.test.ts +0 -119
  123. package/__tests__/firmware-update/firmware-host-binding.test.ts +0 -70
  124. package/__tests__/firmware-update/firmware-update-capabilities.test.ts +0 -13
  125. package/__tests__/firmware-update/firmware-update-plan.test.ts +0 -326
  126. package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +0 -200
  127. package/__tests__/firmware-update/firmware-upload-source.test.ts +0 -70
  128. package/dist/api/firmware/FirmwareArtifactSource.d.ts +0 -26
  129. package/dist/api/firmware/FirmwareArtifactSource.d.ts.map +0 -1
  130. package/dist/api/firmware/FirmwareHostBinding.d.ts +0 -6
  131. package/dist/api/firmware/FirmwareHostBinding.d.ts.map +0 -1
  132. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts +0 -3
  133. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts.map +0 -1
  134. package/dist/api/firmware/FirmwareUpdatePlan.d.ts +0 -24
  135. package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +0 -1
  136. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts +0 -25
  137. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +0 -1
  138. package/dist/types/api/firmwareUpdateCapabilities.d.ts +0 -9
  139. package/dist/types/api/firmwareUpdateCapabilities.d.ts.map +0 -1
  140. package/dist/types/api/firmwareUpdatePlan.d.ts +0 -27
  141. package/dist/types/api/firmwareUpdatePlan.d.ts.map +0 -1
  142. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts +0 -42
  143. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts.map +0 -1
  144. package/src/api/firmware/FirmwareArtifactSource.ts +0 -278
  145. package/src/api/firmware/FirmwareHostBinding.ts +0 -100
  146. package/src/api/firmware/FirmwareUpdateCapabilities.ts +0 -9
  147. package/src/api/firmware/FirmwareUpdatePlan.ts +0 -621
  148. package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +0 -378
  149. package/src/types/api/firmwareUpdateCapabilities.ts +0 -9
  150. package/src/types/api/firmwareUpdatePlan.ts +0 -36
  151. package/src/types/api/firmwareUpdatePreparedPlan.ts +0 -53
@@ -19,7 +19,7 @@ const createCommands = () => {
19
19
  };
20
20
 
21
21
  describe('DeviceCommands failure mapping', () => {
22
- it('does not log DeviceSessionOpen response secrets', async () => {
22
+ it('does not log DeviceSessionGet response secrets', async () => {
23
23
  const commands = createCommands();
24
24
  const log = getLogger(LoggerNames.DeviceCommands);
25
25
  log.messages.length = 0;
@@ -33,7 +33,7 @@ describe('DeviceCommands failure mapping', () => {
33
33
  btc_test_address: 'secret-wallet-address',
34
34
  },
35
35
  } as any,
36
- 'DeviceSessionOpen'
36
+ 'DeviceSessionGet'
37
37
  )
38
38
  ).resolves.toMatchObject({ type: 'DeviceSession' });
39
39
 
@@ -41,7 +41,7 @@ describe('DeviceCommands failure mapping', () => {
41
41
  expect(JSON.stringify(log.messages)).not.toContain('secret-wallet-address');
42
42
  });
43
43
 
44
- it('maps an invalid DeviceSessionOpen resume to WalletSessionInvalid', async () => {
44
+ it('maps an invalid DeviceSessionGet resume to WalletSessionInvalid', async () => {
45
45
  const commands = createCommands();
46
46
 
47
47
  await expect(
@@ -54,7 +54,7 @@ describe('DeviceCommands failure mapping', () => {
54
54
  message: 'Invalid session',
55
55
  },
56
56
  } as any,
57
- 'DeviceSessionOpen'
57
+ 'DeviceSessionGet'
58
58
  )
59
59
  ).rejects.toMatchObject({
60
60
  errorCode: HardwareErrorCode.WalletSessionInvalid,
@@ -66,7 +66,7 @@ describe('DeviceCommands failure mapping', () => {
66
66
  });
67
67
  });
68
68
 
69
- it('maps DeviceSessionOpen user cancellation to ActionCancelled', async () => {
69
+ it('maps wallet-session user cancellation to ActionCancelled', async () => {
70
70
  const commands = createCommands();
71
71
 
72
72
  await expect(
@@ -79,7 +79,7 @@ describe('DeviceCommands failure mapping', () => {
79
79
  message: 'Cancelled on device',
80
80
  },
81
81
  } as any,
82
- 'DeviceSessionOpen'
82
+ 'DeviceSessionAskPassphrase'
83
83
  )
84
84
  ).rejects.toMatchObject({
85
85
  errorCode: HardwareErrorCode.ActionCancelled,
@@ -89,7 +89,7 @@ describe('DeviceCommands failure mapping', () => {
89
89
  it.each([
90
90
  [3, HardwareErrorCode.DeviceCheckUnlockTypeError],
91
91
  [4, HardwareErrorCode.DeviceNotOpenedPassphrase],
92
- ])('maps DeviceSessionOpen subcode %s to its canonical wallet error', async (subcode, code) => {
92
+ ])('maps wallet-session subcode %s to its canonical wallet error', async (subcode, code) => {
93
93
  const commands = createCommands();
94
94
 
95
95
  await expect(
@@ -98,11 +98,46 @@ describe('DeviceCommands failure mapping', () => {
98
98
  type: 'Failure',
99
99
  message: { code: 'Failure_ProcessError', subcode, message: 'Session selection failed' },
100
100
  } as any,
101
- 'DeviceSessionOpen'
101
+ 'DeviceSessionAskPin'
102
102
  )
103
103
  ).rejects.toMatchObject({ errorCode: code });
104
104
  });
105
105
 
106
+ it.each([
107
+ ['DeviceSessionGet', 5, 'Another flow in progress'],
108
+ ['DeviceSessionAskPin', 0, 'Busy'],
109
+ ])('maps %s firmware busy failures to DeviceBusy', async (callType, subcode, message) => {
110
+ const commands = createCommands();
111
+
112
+ await expect(
113
+ commands._filterCommonTypes(
114
+ {
115
+ type: 'Failure',
116
+ message: { code: 'Failure_ProcessError', subcode, message },
117
+ } as any,
118
+ callType
119
+ )
120
+ ).rejects.toMatchObject({ errorCode: HardwareErrorCode.DeviceBusy });
121
+ });
122
+
123
+ it('maps the current AskPin passphrase-disabled response without relying on a subcode', async () => {
124
+ const commands = createCommands();
125
+
126
+ await expect(
127
+ commands._filterCommonTypes(
128
+ {
129
+ type: 'Failure',
130
+ message: {
131
+ code: 'Failure_ProcessError',
132
+ subcode: 0,
133
+ message: 'Passphrase disabled',
134
+ },
135
+ } as any,
136
+ 'DeviceSessionAskPin'
137
+ )
138
+ ).rejects.toMatchObject({ errorCode: HardwareErrorCode.DeviceNotOpenedPassphrase });
139
+ });
140
+
106
141
  it('rejects the Pro2 bootloader DeviceStatusGet unsupported response', async () => {
107
142
  const commands = createCommands();
108
143
 
@@ -1,61 +1,19 @@
1
- import DataManager from '../src/data-manager/DataManager';
2
1
  import { parseConnectSettings } from '../src/data-manager/connectSettings';
3
2
 
4
- import type { RemoteConfigResponse } from '../src/types';
5
-
6
- jest.mock('axios', () => ({
7
- get: jest.fn(),
8
- }));
9
-
10
3
  jest.mock('../src/data/config', () => ({
11
4
  getSDKVersion: jest.fn(() => '1.0.0'),
12
5
  DEFAULT_DOMAIN: 'https://jssdk.onekey.so/1.0.0/',
13
6
  }));
14
7
 
15
- const mockAxiosGet: jest.Mock = jest.requireMock('axios').get;
16
-
17
8
  describe('parseConnectSettings', () => {
18
- const preloadedConfig = {
19
- bridge: {},
20
- classic: { firmware: [], ble: [] },
21
- classic1s: { firmware: [], ble: [] },
22
- classicpure: { firmware: [], ble: [] },
23
- mini: { firmware: [], ble: [] },
24
- touch: { firmware: [], ble: [] },
25
- pro: { firmware: [], ble: [] },
26
- pro2: { firmware: [], ble: [] },
27
- } as unknown as RemoteConfigResponse;
28
-
29
- it('keeps a serializable preloaded config in parsed settings', () => {
30
- const settings = parseConnectSettings({
31
- firmwareManifestMode: 'sdk-managed',
32
- preloadedConfig,
33
- });
34
-
35
- expect(settings.firmwareManifestMode).toBe('sdk-managed');
36
- expect(settings.preloadedConfig).toBe(preloadedConfig);
37
- });
38
-
39
- it('uses the preloaded config before the SDK network client', async () => {
40
- const settings = parseConnectSettings({
41
- firmwareManifestMode: 'sdk-managed',
42
- preloadedConfig,
43
- });
44
-
45
- await DataManager.load(settings);
46
-
47
- expect(mockAxiosGet).not.toHaveBeenCalled();
48
- expect(DataManager.deviceMap.classic).toEqual({ firmware: [], ble: [] });
49
- });
9
+ it('keeps custom configFetcher in parsed settings', () => {
10
+ const configFetcher = jest.fn();
50
11
 
51
- it('fails closed without a preloaded config in external-only mode', async () => {
52
12
  const settings = parseConnectSettings({
53
- firmwareManifestMode: 'external-only',
13
+ fetchConfig: true,
14
+ configFetcher,
54
15
  });
55
16
 
56
- await expect(DataManager.load(settings)).rejects.toThrow(
57
- 'External firmware config snapshot is required'
58
- );
59
- expect(mockAxiosGet).not.toHaveBeenCalled();
17
+ expect(settings.configFetcher).toBe(configFetcher);
60
18
  });
61
19
  });
@@ -1,3 +1,5 @@
1
+ import { TRANSPORT_EVENT } from '@onekeyfe/hd-transport';
2
+
1
3
  import { initConnector, initCore } from '../src/core';
2
4
  import { DataManager } from '../src/data-manager';
3
5
  import TransportManager from '../src/data-manager/TransportManager';
@@ -59,6 +61,63 @@ describe('public device lifecycle events', () => {
59
61
  jest.restoreAllMocks();
60
62
  });
61
63
 
64
+ test('registers the shared device lifecycle listeners exactly once', async () => {
65
+ jest.spyOn(DataManager, 'getSettings').mockReturnValue('react-native' as never);
66
+ core = initCore();
67
+ initConnector();
68
+
69
+ for (const id of ['first-call', 'second-call']) {
70
+ await core.handleMessage({
71
+ id,
72
+ event: IFRAME.CALL,
73
+ type: IFRAME.CALL,
74
+ payload: { method: 'clearSessionCache' },
75
+ } as CoreMessage);
76
+ }
77
+
78
+ expect(DevicePool.emitter.listenerCount(DEVICE.CONNECT)).toBe(1);
79
+ expect(DevicePool.emitter.listenerCount(DEVICE.DISCONNECT)).toBe(1);
80
+ });
81
+
82
+ test('converts an internal transport disconnect into a public KnownDevice snapshot', () => {
83
+ jest.spyOn(DataManager, 'getSettings').mockReturnValue('react-native' as never);
84
+ core = initCore();
85
+ initConnector();
86
+ const messages: CoreMessage[] = [];
87
+ core.on(CORE_EVENT, message => messages.push(message));
88
+ const device = createInitializedDevice('V2');
89
+ DevicePool.devicesCache['ble-connect-id'] = device;
90
+
91
+ DevicePool.emitter.emit(TRANSPORT_EVENT.DEVICE_DISCONNECT, {
92
+ id: 'ble-connect-id',
93
+ connectId: 'ble-connect-id',
94
+ name: 'OneKey Test BLE',
95
+ });
96
+
97
+ const disconnectMessage = messages.find(message => message.type === DEVICE.DISCONNECT);
98
+ expect(disconnectMessage?.payload.device).toMatchObject({
99
+ connectId: 'ble-connect-id',
100
+ serialNo: 'SERIAL-001',
101
+ state: { protocol: 'V2' },
102
+ });
103
+ expect(() => JSON.stringify(disconnectMessage?.payload.device)).not.toThrow();
104
+ });
105
+
106
+ test('treats an acquired BLE device as reusable until the transport disconnects', async () => {
107
+ jest.spyOn(DataManager, 'getSettings').mockReturnValue('desktop-web-ble' as never);
108
+ const device = createInitializedDevice('V2');
109
+ const acquire = jest.spyOn(device, 'acquire').mockResolvedValue(undefined);
110
+ (device as unknown as { deviceAcquired: boolean }).deviceAcquired = true;
111
+ (device as any).commands = { disposed: false };
112
+
113
+ expect(device.isUsedHere()).toBe(true);
114
+ await expect(device.connect('V2')).resolves.toBe(true);
115
+ expect(acquire).not.toHaveBeenCalled();
116
+
117
+ device.markTransportDisconnected();
118
+ expect(device.isUsedHere()).toBe(false);
119
+ });
120
+
62
121
  test.each([
63
122
  ['react-native', 'V1'],
64
123
  ['react-native', 'V2'],
@@ -37,7 +37,6 @@ function createDevice({ protocol }: { protocol: 'V1' | 'V2' }) {
37
37
 
38
38
  describe('DeviceSettings protocol routing', () => {
39
39
  it.each([
40
- ['label', { label: 'Shared Label' }],
41
40
  ['language', { language: 'ja-JP' }],
42
41
  ['brightness', { brightness: 80 }],
43
42
  ['haptic feedback', { hapticFeedback: true }],
@@ -56,6 +55,7 @@ describe('DeviceSettings protocol routing', () => {
56
55
  });
57
56
 
58
57
  it.each([
58
+ ['label', { label: 'Shared Label' }],
59
59
  ['auto lock', { autoLockDelayMs: 60_000 }],
60
60
  ['auto shutdown', { autoShutdownDelayMs: 120_000 }],
61
61
  ['mixed settings', { brightness: 80, autoLockDelayMs: 60_000 }],
@@ -1,6 +1,7 @@
1
1
  import { HardwareErrorCode } from '@onekeyfe/hd-shared';
2
2
 
3
3
  import ClearSessionCache from '../src/api/ClearSessionCache';
4
+ import DeviceWipe from '../src/api/device/DeviceWipe';
4
5
  import {
5
6
  DeviceWalletSessionStore,
6
7
  deviceWalletSessionStore,
@@ -96,6 +97,46 @@ describe('DeviceWalletSessionStore', () => {
96
97
  });
97
98
  });
98
99
 
100
+ describe('Device wipe lifecycle invalidation', () => {
101
+ beforeEach(() => {
102
+ deviceWalletSessionStore.clear();
103
+ });
104
+
105
+ test('clears the old Protocol V2 identity and wallet sessions after wipe succeeds', async () => {
106
+ const device = Device.fromDescriptor({
107
+ id: 'pro2-descriptor',
108
+ path: 'pro2-path',
109
+ protocolType: 'V2',
110
+ } as never);
111
+ device.features = {
112
+ protocol: 'V2',
113
+ deviceId: 'old-device-id',
114
+ unlocked: true,
115
+ passphraseProtection: true,
116
+ } as never;
117
+ device.passphraseState = 'hidden-a';
118
+ deviceWalletSessionStore.set('old-device-id', 'hidden-a', 'old-session');
119
+ deviceWalletSessionStore.set('pro2-path', 'hidden-a', 'temporary-session');
120
+ device.markPreInitialized({ passphraseState: 'hidden-a' });
121
+ device.commands = {
122
+ typedCall: jest.fn().mockResolvedValue({ message: { message: 'accepted' } }),
123
+ } as never;
124
+
125
+ const method = new DeviceWipe({ id: 1, payload: { method: 'deviceWipe' } });
126
+ method.init();
127
+ (method as any).device = device;
128
+
129
+ await expect(method.run()).resolves.toEqual({ message: 'accepted' });
130
+
131
+ expect(device.features).toBeUndefined();
132
+ expect(device.passphraseState).toBeUndefined();
133
+ expect(device.needReloadDevice).toBe(true);
134
+ expect(device.isPreInitializedValid(60_000)).toBe(false);
135
+ expect(deviceWalletSessionStore.get('old-device-id', 'hidden-a')).toBeUndefined();
136
+ expect(deviceWalletSessionStore.get('pro2-path', 'hidden-a')).toBeUndefined();
137
+ });
138
+ });
139
+
99
140
  describe('ClearSessionCache', () => {
100
141
  beforeEach(() => {
101
142
  deviceWalletSessionStore.clear();
@@ -2,7 +2,7 @@ import { EDeviceType, EFirmwareType, HardwareErrorCode } from '@onekeyfe/hd-shar
2
2
 
3
3
  import FirmwareUpdateV2 from '../../src/api/FirmwareUpdateV2';
4
4
  import { getBinary } from '../../src/api/firmware/getBinary';
5
- import { uploadFirmwareFromSource } from '../../src/api/firmware/uploadFirmware';
5
+ import { uploadFirmware } from '../../src/api/firmware/uploadFirmware';
6
6
  import * as utils from '../../src/utils';
7
7
 
8
8
  jest.mock('../../src/data/config', () => ({
@@ -18,8 +18,7 @@ jest.mock('../../src/api/firmware/getBinary', () => ({
18
18
 
19
19
  jest.mock('../../src/api/firmware/uploadFirmware', () => ({
20
20
  updateResources: jest.fn(),
21
- updateResourcesFromSources: jest.fn(),
22
- uploadFirmwareFromSource: jest.fn(),
21
+ uploadFirmware: jest.fn(),
23
22
  }));
24
23
 
25
24
  jest.mock('../../src/device/DevicePool', () => ({
@@ -30,9 +29,7 @@ jest.mock('../../src/device/DevicePool', () => ({
30
29
  }));
31
30
 
32
31
  const mockGetBinary = getBinary as jest.MockedFunction<typeof getBinary>;
33
- const mockUploadFirmwareFromSource = uploadFirmwareFromSource as jest.MockedFunction<
34
- typeof uploadFirmwareFromSource
35
- >;
32
+ const mockUploadFirmware = uploadFirmware as jest.MockedFunction<typeof uploadFirmware>;
36
33
 
37
34
  type DeviceType = 'CLASSIC1S' | 'PURE';
38
35
 
@@ -178,7 +175,7 @@ describe('FirmwareUpdateV2 download-before-reboot safety', () => {
178
175
  expect(mockGetBinary).toHaveBeenCalledTimes(1);
179
176
  expectNoFirmwareMutationCalls(typedCall);
180
177
  expect(acquire).not.toHaveBeenCalled();
181
- expect(mockUploadFirmwareFromSource).not.toHaveBeenCalled();
178
+ expect(mockUploadFirmware).not.toHaveBeenCalled();
182
179
  });
183
180
 
184
181
  it.each([
@@ -219,11 +216,9 @@ describe('FirmwareUpdateV2 download-before-reboot safety', () => {
219
216
  binary: firmwareBinary,
220
217
  } as Awaited<ReturnType<typeof getBinary>>);
221
218
  });
222
- mockUploadFirmwareFromSource.mockImplementation(() => {
219
+ mockUploadFirmware.mockImplementation(() => {
223
220
  callOrder.push('upload');
224
- return Promise.resolve(
225
- expectedResponse as Awaited<ReturnType<typeof uploadFirmwareFromSource>>
226
- );
221
+ return Promise.resolve(expectedResponse as Awaited<ReturnType<typeof uploadFirmware>>);
227
222
  });
228
223
  const { method, typedCall } = createMethod({
229
224
  updateType,
@@ -253,15 +248,15 @@ describe('FirmwareUpdateV2 download-before-reboot safety', () => {
253
248
  },
254
249
  })
255
250
  );
256
- expect(mockUploadFirmwareFromSource).toHaveBeenCalledWith(
251
+ expect(mockUploadFirmware).toHaveBeenCalledWith(
257
252
  updateType,
258
253
  expect.any(Function),
259
254
  expect.any(Function),
260
255
  method.device,
261
- expect.objectContaining({
262
- size: firmwareBinary.byteLength,
263
- }),
264
- true,
256
+ {
257
+ payload: firmwareBinary,
258
+ rebootOnSuccess: true,
259
+ },
265
260
  isUpdateBootloader
266
261
  );
267
262
  }
@@ -276,11 +271,11 @@ describe('FirmwareUpdateV2 download-before-reboot safety', () => {
276
271
  binary: firmwareBinary,
277
272
  } as Awaited<ReturnType<typeof getBinary>>);
278
273
  });
279
- mockUploadFirmwareFromSource.mockImplementation(() => {
274
+ mockUploadFirmware.mockImplementation(() => {
280
275
  callOrder.push('upload');
281
276
  return Promise.resolve({
282
277
  success: true,
283
- } as Awaited<ReturnType<typeof uploadFirmwareFromSource>>);
278
+ } as Awaited<ReturnType<typeof uploadFirmware>>);
284
279
  });
285
280
  const { method, typedCall, acquire } = createMethod({
286
281
  bootloaderMode: true,
@@ -305,9 +300,9 @@ describe('FirmwareUpdateV2 download-before-reboot safety', () => {
305
300
  resolveDownload = resolve;
306
301
  })
307
302
  );
308
- mockUploadFirmwareFromSource.mockResolvedValue({
303
+ mockUploadFirmware.mockResolvedValue({
309
304
  success: true,
310
- } as Awaited<ReturnType<typeof uploadFirmwareFromSource>>);
305
+ } as Awaited<ReturnType<typeof uploadFirmware>>);
311
306
  const { method, typedCall } = createMethod();
312
307
 
313
308
  const runPromise = method.run();
@@ -338,7 +333,7 @@ describe('FirmwareUpdateV2 download-before-reboot safety', () => {
338
333
 
339
334
  expectNoFirmwareMutationCalls(typedCall);
340
335
  expect(acquire).not.toHaveBeenCalled();
341
- expect(mockUploadFirmwareFromSource).not.toHaveBeenCalled();
336
+ expect(mockUploadFirmware).not.toHaveBeenCalled();
342
337
  });
343
338
 
344
339
  it.each([
@@ -347,23 +342,23 @@ describe('FirmwareUpdateV2 download-before-reboot safety', () => {
347
342
  ])(
348
343
  'keeps the non-empty %s binary overload and never downloads it again',
349
344
  async (_kind, binary) => {
350
- mockUploadFirmwareFromSource.mockResolvedValue({
345
+ mockUploadFirmware.mockResolvedValue({
351
346
  success: true,
352
- } as Awaited<ReturnType<typeof uploadFirmwareFromSource>>);
347
+ } as Awaited<ReturnType<typeof uploadFirmware>>);
353
348
  const { method } = createMethod({ binary });
354
349
 
355
350
  await method.run();
356
351
 
357
352
  expect(mockGetBinary).not.toHaveBeenCalled();
358
- expect(mockUploadFirmwareFromSource).toHaveBeenCalledWith(
353
+ expect(mockUploadFirmware).toHaveBeenCalledWith(
359
354
  'firmware',
360
355
  expect.any(Function),
361
356
  expect.any(Function),
362
357
  method.device,
363
- expect.objectContaining({
364
- size: binary.byteLength,
365
- }),
366
- true,
358
+ {
359
+ payload: binary,
360
+ rebootOnSuccess: true,
361
+ },
367
362
  undefined
368
363
  );
369
364
  }
@@ -374,21 +369,17 @@ describe('FirmwareUpdateV2 download-before-reboot safety', () => {
374
369
  ['DataView', new DataView(new Uint8Array([9, 3, 4, 9]).buffer, 1, 2), [3, 4]],
375
370
  ['custom Buffer', createCustomBuffer(4), [1, 2, 3, 4]],
376
371
  ])('normalizes a non-empty %s before rebooting', async (_kind, binary, expectedBytes) => {
377
- let uploadedBytes: number[] = [];
378
- mockUploadFirmwareFromSource.mockImplementation(
379
- async (_updateType, _typedCall, _postMessage, _device, source) => {
380
- uploadedBytes = Array.from(new Uint8Array(await source.readAt(0, source.size)));
381
- return {
382
- success: true,
383
- } as Awaited<ReturnType<typeof uploadFirmwareFromSource>>;
384
- }
385
- );
372
+ mockUploadFirmware.mockResolvedValue({
373
+ success: true,
374
+ } as Awaited<ReturnType<typeof uploadFirmware>>);
386
375
  const { method } = createMethod({ binary });
387
376
 
388
377
  await method.run();
389
378
 
390
379
  expect(mockGetBinary).not.toHaveBeenCalled();
391
- expect(uploadedBytes).toEqual(expectedBytes);
380
+ const normalizedBinary = mockUploadFirmware.mock.calls[0][4].payload;
381
+ expect(normalizedBinary).toBeInstanceOf(ArrayBuffer);
382
+ expect(Array.from(new Uint8Array(normalizedBinary))).toEqual(expectedBytes);
392
383
  });
393
384
 
394
385
  it.each([
@@ -406,6 +397,6 @@ describe('FirmwareUpdateV2 download-before-reboot safety', () => {
406
397
  expect(mockGetBinary).not.toHaveBeenCalled();
407
398
  expectNoFirmwareMutationCalls(typedCall);
408
399
  expect(acquire).not.toHaveBeenCalled();
409
- expect(mockUploadFirmwareFromSource).not.toHaveBeenCalled();
400
+ expect(mockUploadFirmware).not.toHaveBeenCalled();
410
401
  });
411
402
  });
@@ -60,4 +60,21 @@ describe('getLogBlockLabel', () => {
60
60
  expect(getLogBlockLabel({ payload: { method, data: new Uint8Array(1024) } })).toBe(method);
61
61
  }
62
62
  );
63
+
64
+ it.each(['evmSignMessage', 'btcSignMessage', 'evmSignTransaction'])(
65
+ 'blocks request and response payload logging for every API method including %s',
66
+ method => {
67
+ expect(getLogBlockLabel({ method, message: 'sensitive signing payload' })).toBe(method);
68
+ expect(
69
+ getLogBlockLabel({
70
+ event: 'iframe-call',
71
+ payload: { method, message: 'sensitive signing payload' },
72
+ })
73
+ ).toBe(method);
74
+ }
75
+ );
76
+
77
+ it('does not classify events without an API method as method calls', () => {
78
+ expect(getLogBlockLabel({ event: 'DEVICE_EVENT', type: 'device-connect' })).toBeUndefined();
79
+ });
63
80
  });