@onekeyfe/hd-core 1.2.0-alpha.68 → 1.2.0-alpha.69

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 (121) hide show
  1. package/__tests__/check-all-firmware-release-protocol-v2.test.ts +28 -0
  2. package/__tests__/connectSettings.test.ts +5 -47
  3. package/__tests__/firmware-update/firmware-update-v2-download-before-boot.test.ts +31 -59
  4. package/__tests__/protocol-v2-firmware-targets.test.ts +33 -1
  5. package/__tests__/protocol-v2-resources.test.ts +9 -6
  6. package/__tests__/protocol-v2.test.ts +174 -383
  7. package/__tests__/protocolV2FileWrite.test.ts +48 -7
  8. package/dist/api/CheckAllFirmwareRelease.d.ts +2 -1
  9. package/dist/api/CheckAllFirmwareRelease.d.ts.map +1 -1
  10. package/dist/api/FirmwareUpdate.d.ts.map +1 -1
  11. package/dist/api/FirmwareUpdateV2.d.ts +0 -10
  12. package/dist/api/FirmwareUpdateV2.d.ts.map +1 -1
  13. package/dist/api/FirmwareUpdateV3.d.ts +3 -7
  14. package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
  15. package/dist/api/FirmwareUpdateV4.d.ts +6 -25
  16. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  17. package/dist/api/device/DeviceUpdateBootloader.d.ts +1 -5
  18. package/dist/api/device/DeviceUpdateBootloader.d.ts.map +1 -1
  19. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +0 -8
  20. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
  21. package/dist/api/firmware/getBinary.d.ts +0 -7
  22. package/dist/api/firmware/getBinary.d.ts.map +1 -1
  23. package/dist/api/firmware/updateBootloader.d.ts +0 -2
  24. package/dist/api/firmware/updateBootloader.d.ts.map +1 -1
  25. package/dist/api/firmware/uploadFirmware.d.ts +1 -9
  26. package/dist/api/firmware/uploadFirmware.d.ts.map +1 -1
  27. package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
  28. package/dist/api/stellar/StellarSignTransaction.d.ts +1 -1
  29. package/dist/data-manager/DataManager.d.ts +0 -1
  30. package/dist/data-manager/DataManager.d.ts.map +1 -1
  31. package/dist/data-manager/connectSettings.d.ts.map +1 -1
  32. package/dist/device/Device.d.ts +0 -1
  33. package/dist/device/Device.d.ts.map +1 -1
  34. package/dist/index.d.ts +2 -180
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +1041 -3037
  37. package/dist/inject.d.ts.map +1 -1
  38. package/dist/lowLevelInject.d.ts.map +1 -1
  39. package/dist/protocols/protocol-v2/resources.d.ts +1 -1
  40. package/dist/protocols/protocol-v2/resources.d.ts.map +1 -1
  41. package/dist/topLevelInject.d.ts.map +1 -1
  42. package/dist/types/api/checkAllFirmwareRelease.d.ts +0 -4
  43. package/dist/types/api/checkAllFirmwareRelease.d.ts.map +1 -1
  44. package/dist/types/api/deviceUpdateBootloader.d.ts +0 -6
  45. package/dist/types/api/deviceUpdateBootloader.d.ts.map +1 -1
  46. package/dist/types/api/export.d.ts +1 -4
  47. package/dist/types/api/export.d.ts.map +1 -1
  48. package/dist/types/api/firmwareUpdate.d.ts +0 -68
  49. package/dist/types/api/firmwareUpdate.d.ts.map +1 -1
  50. package/dist/types/api/index.d.ts +1 -9
  51. package/dist/types/api/index.d.ts.map +1 -1
  52. package/dist/types/settings.d.ts +1 -14
  53. package/dist/types/settings.d.ts.map +1 -1
  54. package/dist/utils/deviceFeaturesCompat.d.ts +0 -1
  55. package/dist/utils/deviceFeaturesCompat.d.ts.map +1 -1
  56. package/package.json +4 -4
  57. package/src/api/CheckAllFirmwareRelease.ts +25 -61
  58. package/src/api/FirmwareUpdate.ts +1 -13
  59. package/src/api/FirmwareUpdateV2.ts +121 -296
  60. package/src/api/FirmwareUpdateV3.ts +57 -263
  61. package/src/api/FirmwareUpdateV4.ts +287 -865
  62. package/src/api/device/DeviceUpdateBootloader.ts +6 -125
  63. package/src/api/firmware/FirmwareUpdateBaseMethod.ts +1 -72
  64. package/src/api/firmware/updateBootloader.ts +4 -19
  65. package/src/api/firmware/uploadFirmware.ts +22 -140
  66. package/src/api/helpers/protocolV2FileWrite.ts +54 -4
  67. package/src/data-manager/DataManager.ts +54 -59
  68. package/src/data-manager/connectSettings.ts +0 -11
  69. package/src/device/Device.ts +1 -6
  70. package/src/index.ts +0 -5
  71. package/src/inject.ts +2 -22
  72. package/src/lowLevelInject.ts +1 -5
  73. package/src/protocols/protocol-v2/resources.ts +5 -1
  74. package/src/topLevelInject.ts +1 -5
  75. package/src/types/api/checkAllFirmwareRelease.ts +0 -4
  76. package/src/types/api/deviceUpdateBootloader.ts +0 -6
  77. package/src/types/api/export.ts +0 -18
  78. package/src/types/api/firmwareUpdate.ts +0 -75
  79. package/src/types/api/index.ts +0 -14
  80. package/src/types/settings.ts +2 -14
  81. package/src/utils/deviceFeaturesCompat.ts +0 -6
  82. package/__tests__/device-initialize-timeout.test.ts +0 -56
  83. package/__tests__/firmware-update/check-all-firmware-release.test.ts +0 -175
  84. package/__tests__/firmware-update/device-update-bootloader.test.ts +0 -87
  85. package/__tests__/firmware-update/firmware-artifact-source.test.ts +0 -119
  86. package/__tests__/firmware-update/firmware-host-binding.test.ts +0 -70
  87. package/__tests__/firmware-update/firmware-preparation-error.test.ts +0 -27
  88. package/__tests__/firmware-update/firmware-update-bootloader-poll.test.ts +0 -200
  89. package/__tests__/firmware-update/firmware-update-capabilities.test.ts +0 -13
  90. package/__tests__/firmware-update/firmware-update-plan-bootloader-identity.test.ts +0 -394
  91. package/__tests__/firmware-update/firmware-update-plan.test.ts +0 -593
  92. package/__tests__/firmware-update/firmware-update-prepared-plan.test.ts +0 -231
  93. package/__tests__/firmware-update/firmware-update-v3-reconnect.test.ts +0 -63
  94. package/__tests__/firmware-update/firmware-upload-source.test.ts +0 -70
  95. package/dist/api/firmware/FirmwareArtifactSource.d.ts +0 -25
  96. package/dist/api/firmware/FirmwareArtifactSource.d.ts.map +0 -1
  97. package/dist/api/firmware/FirmwareHostBinding.d.ts +0 -6
  98. package/dist/api/firmware/FirmwareHostBinding.d.ts.map +0 -1
  99. package/dist/api/firmware/FirmwarePreparationError.d.ts +0 -3
  100. package/dist/api/firmware/FirmwarePreparationError.d.ts.map +0 -1
  101. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts +0 -3
  102. package/dist/api/firmware/FirmwareUpdateCapabilities.d.ts.map +0 -1
  103. package/dist/api/firmware/FirmwareUpdatePlan.d.ts +0 -25
  104. package/dist/api/firmware/FirmwareUpdatePlan.d.ts.map +0 -1
  105. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts +0 -32
  106. package/dist/api/firmware/FirmwareUpdatePreparedPlan.d.ts.map +0 -1
  107. package/dist/types/api/firmwareUpdateCapabilities.d.ts +0 -9
  108. package/dist/types/api/firmwareUpdateCapabilities.d.ts.map +0 -1
  109. package/dist/types/api/firmwareUpdatePlan.d.ts +0 -28
  110. package/dist/types/api/firmwareUpdatePlan.d.ts.map +0 -1
  111. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts +0 -42
  112. package/dist/types/api/firmwareUpdatePreparedPlan.d.ts.map +0 -1
  113. package/src/api/firmware/FirmwareArtifactSource.ts +0 -278
  114. package/src/api/firmware/FirmwareHostBinding.ts +0 -100
  115. package/src/api/firmware/FirmwarePreparationError.ts +0 -12
  116. package/src/api/firmware/FirmwareUpdateCapabilities.ts +0 -9
  117. package/src/api/firmware/FirmwareUpdatePlan.ts +0 -772
  118. package/src/api/firmware/FirmwareUpdatePreparedPlan.ts +0 -449
  119. package/src/types/api/firmwareUpdateCapabilities.ts +0 -9
  120. package/src/types/api/firmwareUpdatePlan.ts +0 -38
  121. package/src/types/api/firmwareUpdatePreparedPlan.ts +0 -53
@@ -32,15 +32,7 @@ import type {
32
32
  firmwareUpdateV2,
33
33
  firmwareUpdateV3,
34
34
  firmwareUpdateV4,
35
- getFirmwareUpdateHostBindingGeneration,
36
- registerFirmwareUpdateHostBinding,
37
- unregisterFirmwareUpdateHostBinding,
38
35
  } from './firmwareUpdate';
39
- import type { getFirmwareUpdateCapabilities } from './firmwareUpdateCapabilities';
40
- import type {
41
- prepareFirmwareUpdatePlan,
42
- validateFirmwareUpdatePreparedPlan,
43
- } from './firmwareUpdatePreparedPlan';
44
36
  import type { promptWebDeviceAccess } from './promptWebDeviceAccess';
45
37
  import type { deviceReset } from './deviceReset';
46
38
  import type { deviceRecovery } from './deviceRecovery';
@@ -247,12 +239,6 @@ export type CoreApi = {
247
239
  firmwareUpdateV2: typeof firmwareUpdateV2;
248
240
  firmwareUpdateV3: typeof firmwareUpdateV3;
249
241
  firmwareUpdateV4: typeof firmwareUpdateV4;
250
- registerFirmwareUpdateHostBinding: typeof registerFirmwareUpdateHostBinding;
251
- unregisterFirmwareUpdateHostBinding: typeof unregisterFirmwareUpdateHostBinding;
252
- getFirmwareUpdateHostBindingGeneration: typeof getFirmwareUpdateHostBindingGeneration;
253
- getFirmwareUpdateCapabilities: typeof getFirmwareUpdateCapabilities;
254
- prepareFirmwareUpdatePlan: typeof prepareFirmwareUpdatePlan;
255
- validateFirmwareUpdatePreparedPlan: typeof validateFirmwareUpdatePreparedPlan;
256
242
  cipherKeyValue: typeof cipherKeyValue;
257
243
 
258
244
  /**
@@ -31,8 +31,6 @@ export type ConnectSettings = {
31
31
  timestamp: number;
32
32
  isFrame?: boolean;
33
33
  preRelease?: boolean;
34
- firmwareManifestMode?: 'sdk-managed' | 'external-only';
35
- preloadedConfig?: RemoteConfigResponse;
36
34
  fetchConfig?: boolean;
37
35
  extension?: string;
38
36
  configFetcher?: (url: string) => Promise<RemoteConfigResponse | null>;
@@ -60,7 +58,6 @@ export type IProtocolV2FirmwareComponent = {
60
58
  fingerprint?: string;
61
59
  /** OKPP payload hash, used to detect same-version package changes. */
62
60
  payloadHash?: string;
63
- expectedSize?: number;
64
61
  version?: IVersionArray;
65
62
  };
66
63
 
@@ -70,7 +67,8 @@ export type IProtocolV2ResourceType =
70
67
  | 'wallpaper'
71
68
  | 'translations'
72
69
  | 'roobert'
73
- | 'noto';
70
+ | 'noto'
71
+ | 'firmware_logo';
74
72
 
75
73
  /** Pro2 RES package descriptor. Hashes identify content without a human-managed version. */
76
74
  export type IProtocolV2Resource = {
@@ -113,8 +111,6 @@ export type IProtocolV2ResourceBundle = {
113
111
  name: string;
114
112
  /** Download URL. */
115
113
  url: string;
116
- fingerprint?: string;
117
- expectedSize?: number;
118
114
  /** Device target path, such as vol0:/bundles/images/images.okpkg. */
119
115
  devicePath: string;
120
116
  /** okpkg payload_version used to skip matching content after FileRead. */
@@ -136,16 +132,10 @@ export type IFirmwareReleaseInfo = {
136
132
  firmwareType?: EFirmwareType;
137
133
  /** Firmware UI resource */
138
134
  resource?: string;
139
- resourceFingerprint?: string;
140
- resourceExpectedSize?: number;
141
135
  /** Firmware full UI resource */
142
136
  fullResource?: string;
143
- fullResourceFingerprint?: string;
144
- fullResourceExpectedSize?: number;
145
137
  fullResourceRange?: string[];
146
138
  bootloaderResource?: string;
147
- bootloaderFingerprint?: string;
148
- bootloaderExpectedSize?: number;
149
139
  bootloaderVersion?: IVersionArray;
150
140
  displayBootloaderVersion?: IVersionArray;
151
141
  bootloaderRelatedFirmwareVersion?: IVersionArray;
@@ -158,7 +148,6 @@ export type IFirmwareReleaseInfo = {
158
148
  [k in ILocale]: string;
159
149
  };
160
150
  fingerprint: string;
161
- expectedSize?: number;
162
151
  version: IVersionArray;
163
152
  changelog: {
164
153
  [k in ILocale]: string;
@@ -174,7 +163,6 @@ export type IBLEFirmwareReleaseInfo = {
174
163
  webUpdate: string;
175
164
  fingerprint: string;
176
165
  fingerprintWeb: string;
177
- expectedSize?: number;
178
166
  version: IVersionArray;
179
167
  changelog: {
180
168
  [k in ILocale]: string;
@@ -37,12 +37,6 @@ export const resolveDeviceSerialNo = (features?: DeviceFeaturesInput): string =>
37
37
  );
38
38
  };
39
39
 
40
- export const resolveDeviceBootloaderMode = (features?: DeviceFeaturesInput): boolean => {
41
- if (!features) return false;
42
- const compatible = asCompatibleFeatures(features);
43
- return (compatible.bootloaderMode ?? compatible.bootloader_mode) === true;
44
- };
45
-
46
40
  export const resolveDeviceType = (features?: DeviceFeaturesInput): IDeviceType => {
47
41
  if (!features || typeof features !== 'object') {
48
42
  return EDeviceType.Unknown;
@@ -1,56 +0,0 @@
1
- import { Device } from '../src/device/Device';
2
- import TransportManager from '../src/data-manager/TransportManager';
3
-
4
- jest.mock('../src/data/config', () => ({
5
- getSDKVersion: jest.fn(() => '1.0.0'),
6
- DEFAULT_DOMAIN: 'https://jssdk.onekey.so/1.0.0/',
7
- }));
8
-
9
- function buildV1Device() {
10
- const device = Object.create(Device.prototype) as Device;
11
- const typedCall = jest.fn(() => Promise.resolve({ message: { device_id: 'device' } }));
12
- Object.assign(device, {
13
- commands: { typedCall },
14
- stateStore: { getState: () => undefined },
15
- isProtocolV2: () => false,
16
- _updateFeatures: jest.fn(),
17
- getInternalState: jest.fn(() => undefined),
18
- });
19
- return { device, typedCall };
20
- }
21
-
22
- describe('Device.initialize Protocol V1 timeout', () => {
23
- beforeEach(() => {
24
- jest.spyOn(TransportManager, 'reconfigure').mockResolvedValue(undefined);
25
- });
26
-
27
- afterEach(() => {
28
- jest.restoreAllMocks();
29
- });
30
-
31
- test('passes a custom Initialize timeout through to typedCall', async () => {
32
- const { device, typedCall } = buildV1Device();
33
-
34
- await device.initialize({ timeoutMs: 2500 });
35
-
36
- expect(typedCall).toHaveBeenCalledWith(
37
- 'Initialize',
38
- 'Features',
39
- expect.objectContaining({ is_contains_attach: true }),
40
- { timeoutMs: 2500 }
41
- );
42
- });
43
-
44
- test('keeps the 25s Initialize timeout by default', async () => {
45
- const { device, typedCall } = buildV1Device();
46
-
47
- await device.initialize();
48
-
49
- expect(typedCall).toHaveBeenCalledWith(
50
- 'Initialize',
51
- 'Features',
52
- expect.objectContaining({ is_contains_attach: true }),
53
- { timeoutMs: 25 * 1000 }
54
- );
55
- });
56
- });
@@ -1,175 +0,0 @@
1
- import { EDeviceType, EFirmwareType, ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
2
-
3
- import CheckAllFirmwareRelease from '../../src/api/CheckAllFirmwareRelease';
4
- import { buildFirmwareUpdatePlan } from '../../src/api/firmware/FirmwareUpdatePlan';
5
- import {
6
- getBleFirmwareReleaseInfo,
7
- getBootloaderReleaseInfo,
8
- getFirmwareReleaseInfo,
9
- } from '../../src/api/firmware/releaseHelper';
10
-
11
- jest.mock('../../src/data/config', () => ({
12
- getSDKVersion: jest.fn(() => '1.0.0'),
13
- DEFAULT_DOMAIN: 'https://jssdk.onekey.so/1.0.0/',
14
- }));
15
-
16
- jest.mock('../../src/api/firmware/FirmwareUpdatePlan', () => ({
17
- buildFirmwareUpdatePlan: jest.fn(),
18
- validateFirmwareUpdatePlanForceTargets: jest.fn(value => value ?? []),
19
- }));
20
-
21
- jest.mock('../../src/api/firmware/releaseHelper', () => ({
22
- getBleFirmwareReleaseInfo: jest.fn(),
23
- getBootloaderReleaseInfo: jest.fn(),
24
- getFirmwareReleaseInfo: jest.fn(),
25
- }));
26
-
27
- const mockBuildFirmwareUpdatePlan = buildFirmwareUpdatePlan as jest.MockedFunction<
28
- typeof buildFirmwareUpdatePlan
29
- >;
30
- const mockGetBleFirmwareReleaseInfo = getBleFirmwareReleaseInfo as jest.MockedFunction<
31
- typeof getBleFirmwareReleaseInfo
32
- >;
33
- const mockGetBootloaderReleaseInfo = getBootloaderReleaseInfo as jest.MockedFunction<
34
- typeof getBootloaderReleaseInfo
35
- >;
36
- const mockGetFirmwareReleaseInfo = getFirmwareReleaseInfo as jest.MockedFunction<
37
- typeof getFirmwareReleaseInfo
38
- >;
39
-
40
- const noUpdate = {
41
- status: 'valid' as const,
42
- release: undefined,
43
- };
44
-
45
- const createMethod = (serialNo = 'device-id') => {
46
- const method = new CheckAllFirmwareRelease({
47
- id: 1,
48
- payload: {
49
- method: 'checkAllFirmwareRelease',
50
- platform: 'native',
51
- },
52
- });
53
- method.init();
54
- method.device = {
55
- isProtocolV2: jest.fn(() => false),
56
- features: {
57
- deviceType: EDeviceType.Classic1s,
58
- serialNo,
59
- firmwareType: EFirmwareType.Universal,
60
- firmwareVersion: '1.0.0',
61
- bootloaderVersion: '1.0.0',
62
- },
63
- } as typeof method.device;
64
- return method;
65
- };
66
-
67
- const createMethodWithForceTargets = () => {
68
- const method = createMethod();
69
- method.payload = {
70
- ...method.payload,
71
- forceUpdateTargets: ['firmware', 'resource'],
72
- };
73
- return method;
74
- };
75
-
76
- describe('CheckAllFirmwareRelease', () => {
77
- beforeEach(() => {
78
- jest.clearAllMocks();
79
- mockGetFirmwareReleaseInfo.mockReturnValue(noUpdate);
80
- mockGetBootloaderReleaseInfo.mockReturnValue(noUpdate);
81
- mockGetBleFirmwareReleaseInfo.mockReturnValue(noUpdate);
82
- });
83
-
84
- test('keeps release information available when an optional Plan cannot be built', async () => {
85
- const firmware = {
86
- status: 'outdated' as const,
87
- release: {
88
- url: 'https://firmware.onekey.so/classic/firmware.bin',
89
- version: [3, 0, 0],
90
- },
91
- };
92
- mockGetFirmwareReleaseInfo.mockReturnValue(firmware);
93
- mockBuildFirmwareUpdatePlan.mockImplementation(() => {
94
- throw ERRORS.TypedError(HardwareErrorCode.RuntimeError, 'Plan cannot be built', {
95
- firmwareUpdateCode: 'FirmwarePlanInvalid',
96
- });
97
- });
98
-
99
- await expect(createMethod('').run()).resolves.toEqual(
100
- expect.objectContaining({
101
- firmware,
102
- bootloader: noUpdate,
103
- ble: noUpdate,
104
- firmwareUpdatePlan: undefined,
105
- })
106
- );
107
- });
108
-
109
- test('returns an optional Plan when the builder succeeds', async () => {
110
- const plan = {
111
- schemaVersion: 2 as const,
112
- planDigest: 'a'.repeat(64),
113
- executor: 'v3' as const,
114
- deviceIdentity: 'device-id',
115
- deviceModel: EDeviceType.Classic1s,
116
- firmwareType: EFirmwareType.Universal,
117
- platform: 'native' as const,
118
- artifacts: [],
119
- targetsToUpdate: [],
120
- };
121
- mockBuildFirmwareUpdatePlan.mockReturnValue(plan);
122
-
123
- await expect(createMethod().run()).resolves.toEqual(
124
- expect.objectContaining({
125
- firmwareUpdatePlan: plan,
126
- })
127
- );
128
- });
129
-
130
- test('passes host-selected update targets to the Plan builder', async () => {
131
- mockBuildFirmwareUpdatePlan.mockReturnValue({
132
- schemaVersion: 2,
133
- planDigest: 'a'.repeat(64),
134
- executor: 'v2',
135
- deviceIdentity: 'device-id',
136
- deviceModel: EDeviceType.Classic1s,
137
- firmwareType: EFirmwareType.Universal,
138
- platform: 'native',
139
- artifacts: [],
140
- targetsToUpdate: [],
141
- });
142
-
143
- await createMethodWithForceTargets().run();
144
-
145
- expect(mockBuildFirmwareUpdatePlan).toHaveBeenCalledWith(
146
- expect.objectContaining({
147
- forceUpdateTargets: ['firmware', 'resource'],
148
- })
149
- );
150
- });
151
-
152
- test('does not hide a Plan failure for an explicitly forced target', async () => {
153
- const planError = ERRORS.TypedError(
154
- HardwareErrorCode.RuntimeError,
155
- 'Forced firmware target is unavailable',
156
- {
157
- firmwareUpdateCode: 'FirmwarePlanInvalid',
158
- }
159
- );
160
- mockBuildFirmwareUpdatePlan.mockImplementation(() => {
161
- throw planError;
162
- });
163
-
164
- await expect(createMethodWithForceTargets().run()).rejects.toBe(planError);
165
- });
166
-
167
- test('does not hide unexpected Plan builder failures', async () => {
168
- const unexpectedError = new Error('unexpected builder failure');
169
- mockBuildFirmwareUpdatePlan.mockImplementation(() => {
170
- throw unexpectedError;
171
- });
172
-
173
- await expect(createMethod().run()).rejects.toBe(unexpectedError);
174
- });
175
- });
@@ -1,87 +0,0 @@
1
- import { EDeviceType, EFirmwareType, ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
2
-
3
- import DeviceUpdateBootloader from '../../src/api/device/DeviceUpdateBootloader';
4
- import {
5
- registerFirmwareUpdateHostBinding,
6
- unregisterFirmwareUpdateHostBinding,
7
- } from '../../src/api/firmware/FirmwareHostBinding';
8
-
9
- jest.mock('../../src/api/firmware/FirmwareUpdatePreparedPlan', () => ({
10
- assertFirmwareUpdatePreparedPlanBinding: jest.fn(),
11
- assertFirmwareUpdatePreparedPlanDeviceIdentity: jest.fn(),
12
- }));
13
-
14
- jest.mock('../../src/data-manager', () => ({
15
- DataManager: {
16
- getSettings: jest.fn(),
17
- isBleConnect: jest.fn(),
18
- },
19
- }));
20
-
21
- jest.mock('../../src/device/DevicePool', () => ({
22
- DevicePool: {},
23
- }));
24
-
25
- const artifact = {
26
- artifactRef: `fw:${'a'.repeat(64)}`,
27
- size: 4,
28
- sha256: 'a'.repeat(64),
29
- };
30
-
31
- const createMethod = () => {
32
- const closeError = new Error('artifact reader close failed');
33
- const close = jest.fn().mockRejectedValue(closeError);
34
- const artifactReader = {
35
- open: jest.fn().mockResolvedValue({ readerId: 'reader-1', size: artifact.size }),
36
- read: jest.fn(),
37
- close,
38
- };
39
- const hostBindingGeneration = registerFirmwareUpdateHostBinding({ artifactReader });
40
- const method = new DeviceUpdateBootloader({
41
- id: 1,
42
- payload: {
43
- method: 'deviceUpdateBootloader',
44
- artifact,
45
- hostBindingGeneration,
46
- preparedPlan: {},
47
- },
48
- });
49
- (method as any).device = {
50
- features: {
51
- deviceType: EDeviceType.Touch,
52
- serialNo: 'touch-device-id',
53
- },
54
- getCurrentDeviceType: () => EDeviceType.Touch,
55
- getCurrentFirmwareType: () => EFirmwareType.Universal,
56
- };
57
- return { close, closeError, method };
58
- };
59
-
60
- describe('DeviceUpdateBootloader artifact source cleanup', () => {
61
- afterEach(() => {
62
- unregisterFirmwareUpdateHostBinding();
63
- jest.restoreAllMocks();
64
- });
65
-
66
- test('does not replace a successful update result when source close fails', async () => {
67
- const { close, method } = createMethod();
68
- jest.spyOn(method, 'updateTouchBootloader').mockResolvedValue(true);
69
-
70
- await expect(method.run()).resolves.toBe(true);
71
-
72
- expect(close).toHaveBeenCalledWith({ readerId: 'reader-1' });
73
- });
74
-
75
- test('does not replace the original hardware error when source close fails', async () => {
76
- const { close, method } = createMethod();
77
- const hardwareError = ERRORS.TypedError(
78
- HardwareErrorCode.FirmwareError,
79
- 'original bootloader hardware error'
80
- );
81
- jest.spyOn(method, 'updateTouchBootloader').mockRejectedValue(hardwareError);
82
-
83
- await expect(method.run()).rejects.toBe(hardwareError);
84
-
85
- expect(close).toHaveBeenCalledWith({ readerId: 'reader-1' });
86
- });
87
- });
@@ -1,119 +0,0 @@
1
- import {
2
- MAX_FIRMWARE_ARTIFACT_READ_BYTES,
3
- openFirmwareByteSource,
4
- writeFirmwareByteSource,
5
- } from '../../src/api/firmware/FirmwareArtifactSource';
6
-
7
- import type { FirmwareArtifactReader } from '../../src/types/api/firmwareUpdate';
8
-
9
- const artifact = {
10
- artifactRef: `fw:${'a'.repeat(64)}`,
11
- size: 6,
12
- sha256: 'b'.repeat(64),
13
- };
14
-
15
- const createReader = () => {
16
- const open = jest.fn(() => Promise.resolve({ readerId: 'reader-1', size: artifact.size }));
17
- const read = jest.fn(({ offset, length }: { readerId: string; offset: number; length: number }) =>
18
- Promise.resolve({
19
- data: Uint8Array.from([1, 2, 3, 4, 5, 6]).slice(offset, offset + length).buffer,
20
- bytesRead: length,
21
- eof: offset + length === artifact.size,
22
- })
23
- );
24
- const close = jest.fn(() => Promise.resolve());
25
- const reader: FirmwareArtifactReader = { open, read, close };
26
- return { reader, open, read, close };
27
- };
28
-
29
- describe('FirmwareArtifactSource', () => {
30
- it('reads an opaque artifact through bounded sequential reads', async () => {
31
- const { reader, close } = createReader();
32
- const source = await openFirmwareByteSource({ artifact, reader });
33
- if (!source) {
34
- throw new Error('Expected a firmware byte source');
35
- }
36
-
37
- const writes: Array<{ offset: number; data: number[] }> = [];
38
- await writeFirmwareByteSource({
39
- source,
40
- chunkSize: 4,
41
- write: ({ data, sourceOffset, length }) => {
42
- writes.push({
43
- offset: sourceOffset,
44
- data: Array.from(new Uint8Array(data)),
45
- });
46
- return Promise.resolve(length);
47
- },
48
- });
49
- await source.close();
50
-
51
- expect(writes).toEqual([
52
- { offset: 0, data: [1, 2, 3, 4] },
53
- { offset: 4, data: [5, 6] },
54
- ]);
55
- expect(close).toHaveBeenCalledWith({ readerId: 'reader-1' });
56
- });
57
-
58
- it('rejects a reader whose opened size differs from the receipt', async () => {
59
- const { reader, open, close } = createReader();
60
- open.mockResolvedValue({
61
- readerId: 'reader-1',
62
- size: artifact.size + 1,
63
- });
64
-
65
- await expect(openFirmwareByteSource({ artifact, reader })).rejects.toMatchObject({
66
- params: {
67
- firmwareUpdateCode: 'FirmwareArtifactReceiptMismatch',
68
- },
69
- });
70
- expect(close).toHaveBeenCalledWith({ readerId: 'reader-1' });
71
- });
72
-
73
- it('rejects paths and over-limit reads before invoking the host', async () => {
74
- const { reader, read } = createReader();
75
- await expect(
76
- openFirmwareByteSource({
77
- artifact: { ...artifact, artifactRef: '/tmp/firmware.bin' },
78
- reader,
79
- })
80
- ).rejects.toMatchObject({
81
- params: {
82
- firmwareUpdateCode: 'FirmwareArtifactReceiptMismatch',
83
- },
84
- });
85
-
86
- const source = await openFirmwareByteSource({ artifact, reader });
87
- if (!source) {
88
- throw new Error('Expected a firmware byte source');
89
- }
90
- await expect(
91
- writeFirmwareByteSource({
92
- source,
93
- chunkSize: MAX_FIRMWARE_ARTIFACT_READ_BYTES + 1,
94
- write: ({ length }) => Promise.resolve(length),
95
- })
96
- ).rejects.toMatchObject({
97
- params: {
98
- firmwareUpdateCode: 'FirmwareArtifactReadTooLarge',
99
- },
100
- });
101
- expect(read).not.toHaveBeenCalled();
102
- await source.close();
103
- });
104
-
105
- it('closes stale readers when open returns invalid metadata', async () => {
106
- const { reader, open, close } = createReader();
107
- open.mockResolvedValue({
108
- readerId: '',
109
- size: artifact.size,
110
- });
111
-
112
- await expect(openFirmwareByteSource({ artifact, reader })).rejects.toMatchObject({
113
- params: {
114
- firmwareUpdateCode: 'FirmwareArtifactReceiptMismatch',
115
- },
116
- });
117
- expect(close).not.toHaveBeenCalled();
118
- });
119
- });
@@ -1,70 +0,0 @@
1
- import {
2
- getFirmwareUpdateHostBindingGeneration,
3
- registerFirmwareUpdateHostBinding,
4
- resolveFirmwareUpdateHostBinding,
5
- unregisterFirmwareUpdateHostBinding,
6
- } from '../../src/api/firmware/FirmwareHostBinding';
7
-
8
- const createBinding = () => ({
9
- artifactReader: {
10
- open: jest.fn(() => Promise.resolve({ readerId: 'reader-1', size: 4 })),
11
- read: jest.fn(() =>
12
- Promise.resolve({
13
- data: new ArrayBuffer(4),
14
- bytesRead: 4,
15
- eof: true,
16
- })
17
- ),
18
- close: jest.fn(() => Promise.resolve()),
19
- },
20
- });
21
-
22
- describe('firmware host binding generation', () => {
23
- afterEach(() => {
24
- unregisterFirmwareUpdateHostBinding();
25
- });
26
-
27
- test('invalidates callbacks from a replaced generation', async () => {
28
- const staleBinding = createBinding();
29
- const staleGeneration = registerFirmwareUpdateHostBinding(staleBinding);
30
- const stale = resolveFirmwareUpdateHostBinding(staleGeneration);
31
- const activeGeneration = registerFirmwareUpdateHostBinding(createBinding());
32
-
33
- expect(activeGeneration).toBeGreaterThan(staleGeneration);
34
- expect(getFirmwareUpdateHostBindingGeneration()).toBe(activeGeneration);
35
- await expect(
36
- stale.artifactReader.read({
37
- readerId: 'reader-1',
38
- offset: 0,
39
- length: 4,
40
- })
41
- ).rejects.toMatchObject({
42
- params: {
43
- firmwareUpdateCode: 'FirmwareArtifactReaderInvalid',
44
- },
45
- });
46
- expect(unregisterFirmwareUpdateHostBinding(staleGeneration)).toBe(false);
47
- expect(getFirmwareUpdateHostBindingGeneration()).toBe(activeGeneration);
48
- });
49
-
50
- test('closes an artifact opened during a generation race', async () => {
51
- const binding = createBinding();
52
- binding.artifactReader.open.mockImplementationOnce(() => {
53
- registerFirmwareUpdateHostBinding(createBinding());
54
- return Promise.resolve({ readerId: 'stale-reader', size: 4 });
55
- });
56
- const generation = registerFirmwareUpdateHostBinding(binding);
57
- const guarded = resolveFirmwareUpdateHostBinding(generation);
58
-
59
- await expect(
60
- guarded.artifactReader.open({ artifactRef: `fw:${'a'.repeat(64)}` })
61
- ).rejects.toMatchObject({
62
- params: {
63
- firmwareUpdateCode: 'FirmwareArtifactReaderInvalid',
64
- },
65
- });
66
- expect(binding.artifactReader.close).toHaveBeenCalledWith({
67
- readerId: 'stale-reader',
68
- });
69
- });
70
- });
@@ -1,27 +0,0 @@
1
- import { ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
2
-
3
- import { normalizeFirmwarePreparationError } from '../../src/api/firmware/FirmwarePreparationError';
4
-
5
- describe('normalizeFirmwarePreparationError', () => {
6
- test('preserves structured firmware invariant errors', () => {
7
- const error = ERRORS.TypedError(
8
- HardwareErrorCode.RuntimeError,
9
- 'Firmware must be prepared by the external firmware host',
10
- {
11
- firmwareUpdateCode: 'FirmwareArtifactsNotPrepared',
12
- artifactName: 'firmware',
13
- }
14
- );
15
-
16
- expect(normalizeFirmwarePreparationError(error)).toBe(error);
17
- });
18
-
19
- test('wraps ordinary preparation failures as firmware download errors', () => {
20
- const error = normalizeFirmwarePreparationError(new Error('request failed'));
21
-
22
- expect(error).toMatchObject({
23
- errorCode: HardwareErrorCode.FirmwareUpdateDownloadFailed,
24
- message: 'request failed',
25
- });
26
- });
27
- });