@onekeyfe/hd-core 1.2.0-alpha.20 → 1.2.0-alpha.21

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 (94) hide show
  1. package/__tests__/device-lifecycle-events.test.ts +1 -1
  2. package/__tests__/device-settings.test.ts +110 -5
  3. package/__tests__/device-state-events.test.ts +3 -3
  4. package/__tests__/device-state-mapper.test.ts +15 -3
  5. package/__tests__/device-state-store.test.ts +1 -1
  6. package/__tests__/deviceSettings.test.ts +55 -15
  7. package/__tests__/evmLedgerLegacySafety.test.ts +6 -5
  8. package/__tests__/get-device-state.test.ts +7 -0
  9. package/__tests__/protocol-v2.test.ts +40 -153
  10. package/__tests__/public-device-state-api.test.ts +19 -15
  11. package/__tests__/public-pro2-api-boundary.test.ts +20 -1
  12. package/dist/api/BaseMethod.d.ts +0 -3
  13. package/dist/api/BaseMethod.d.ts.map +1 -1
  14. package/dist/api/UploadPortfolio.d.ts +0 -1
  15. package/dist/api/UploadPortfolio.d.ts.map +1 -1
  16. package/dist/api/device/DeviceSettings.d.ts.map +1 -1
  17. package/dist/api/device/DeviceUnlock.d.ts +1 -1
  18. package/dist/api/device/DeviceUnlock.d.ts.map +1 -1
  19. package/dist/api/index.d.ts +0 -3
  20. package/dist/api/index.d.ts.map +1 -1
  21. package/dist/core/RequestQueue.d.ts +1 -19
  22. package/dist/core/RequestQueue.d.ts.map +1 -1
  23. package/dist/core/index.d.ts +0 -1
  24. package/dist/core/index.d.ts.map +1 -1
  25. package/dist/device/Device.d.ts +1 -1
  26. package/dist/device/DeviceFeaturesState.d.ts +0 -1
  27. package/dist/device/DeviceFeaturesState.d.ts.map +1 -1
  28. package/dist/device/DeviceStateMapper.d.ts.map +1 -1
  29. package/dist/deviceProfile/buildDeviceFeatures.d.ts.map +1 -1
  30. package/dist/events/call.d.ts +0 -7
  31. package/dist/events/call.d.ts.map +1 -1
  32. package/dist/events/core.d.ts +2 -2
  33. package/dist/events/core.d.ts.map +1 -1
  34. package/dist/events/iframe.d.ts +0 -1
  35. package/dist/events/iframe.d.ts.map +1 -1
  36. package/dist/index.d.ts +59 -55
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +169 -310
  39. package/dist/inject.d.ts +2 -3
  40. package/dist/inject.d.ts.map +1 -1
  41. package/dist/lowLevelInject.d.ts +1 -2
  42. package/dist/lowLevelInject.d.ts.map +1 -1
  43. package/dist/topLevelInject.d.ts.map +1 -1
  44. package/dist/types/api/deviceSettings.d.ts +2 -2
  45. package/dist/types/api/deviceSettings.d.ts.map +1 -1
  46. package/dist/types/api/deviceUnlock.d.ts +2 -2
  47. package/dist/types/api/deviceUnlock.d.ts.map +1 -1
  48. package/dist/types/api/index.d.ts +1 -5
  49. package/dist/types/api/index.d.ts.map +1 -1
  50. package/dist/types/api/protocolV2.d.ts +1 -9
  51. package/dist/types/api/protocolV2.d.ts.map +1 -1
  52. package/dist/types/device.d.ts +4 -4
  53. package/dist/types/device.d.ts.map +1 -1
  54. package/dist/utils/deviceSettings.d.ts +36 -7
  55. package/dist/utils/deviceSettings.d.ts.map +1 -1
  56. package/dist/utils/index.d.ts +2 -1
  57. package/dist/utils/index.d.ts.map +1 -1
  58. package/package.json +4 -4
  59. package/src/api/BaseMethod.ts +3 -9
  60. package/src/api/UploadPortfolio.ts +2 -12
  61. package/src/api/device/DeviceSettings.ts +66 -5
  62. package/src/api/device/DeviceUnlock.ts +2 -1
  63. package/src/api/index.ts +0 -3
  64. package/src/core/RequestQueue.ts +4 -123
  65. package/src/core/index.ts +25 -31
  66. package/src/device/Device.ts +1 -1
  67. package/src/device/DeviceFeaturesState.ts +0 -9
  68. package/src/device/DeviceStateMapper.ts +8 -7
  69. package/src/deviceProfile/buildDeviceFeatures.ts +2 -1
  70. package/src/events/call.ts +0 -6
  71. package/src/events/core.ts +0 -2
  72. package/src/events/iframe.ts +0 -1
  73. package/src/index.ts +0 -4
  74. package/src/inject.ts +0 -10
  75. package/src/lowLevelInject.ts +0 -3
  76. package/src/topLevelInject.ts +0 -2
  77. package/src/types/api/deviceSettings.ts +17 -2
  78. package/src/types/api/deviceUnlock.ts +5 -2
  79. package/src/types/api/index.ts +0 -7
  80. package/src/types/api/protocolV2.ts +0 -31
  81. package/src/types/device.ts +5 -3
  82. package/src/utils/deviceSettings.ts +130 -56
  83. package/src/utils/index.ts +18 -1
  84. package/__tests__/RequestQueue.test.ts +0 -140
  85. package/__tests__/UploadPortfolio.test.ts +0 -46
  86. package/dist/api/protocol-v2/DeviceSettingsGet.d.ts +0 -6
  87. package/dist/api/protocol-v2/DeviceSettingsGet.d.ts.map +0 -1
  88. package/dist/api/protocol-v2/DeviceSettingsPageShow.d.ts +0 -16
  89. package/dist/api/protocol-v2/DeviceSettingsPageShow.d.ts.map +0 -1
  90. package/dist/api/protocol-v2/DeviceSettingsSet.d.ts +0 -12
  91. package/dist/api/protocol-v2/DeviceSettingsSet.d.ts.map +0 -1
  92. package/src/api/protocol-v2/DeviceSettingsGet.ts +0 -18
  93. package/src/api/protocol-v2/DeviceSettingsPageShow.ts +0 -70
  94. package/src/api/protocol-v2/DeviceSettingsSet.ts +0 -44
@@ -1,28 +1,43 @@
1
- import type { SafetyCheckLevel, Success } from '@onekeyfe/hd-transport';
1
+ import type { Enum_SafetyCheckLevel, Success } from '@onekeyfe/hd-transport';
2
2
  import type { CommonParams, Response } from '../params';
3
3
 
4
4
  export type DeviceSettingsParams = {
5
5
  language?: string;
6
6
  label?: string;
7
7
  usePassphrase?: boolean;
8
+ /** Protocol V1 only. */
8
9
  homescreen?: string;
10
+ /** Protocol V1 only. */
9
11
  passphraseSource?: number;
10
12
  autoLockDelayMs?: number;
13
+ /** Protocol V1 only. */
11
14
  displayRotation?: number;
15
+ /** Protocol V1 only. */
12
16
  passphraseAlwaysOnDevice?: boolean;
13
- safetyChecks?: SafetyCheckLevel;
17
+ /** Protocol V1 only. Uses Enum_SafetyCheckLevel numeric values. */
18
+ safetyChecks?: Enum_SafetyCheckLevel;
19
+ /** Protocol V1 only; the current Protocol V2 schema has no matching field. */
14
20
  experimentalFeatures?: boolean;
15
21
  autoShutdownDelayMs?: number;
22
+ /** Protocol V1 only; opens the legacy device-side brightness flow. */
16
23
  changeBrightness?: boolean;
24
+ /** Protocol V2 only. */
17
25
  brightness?: number;
18
26
  hapticFeedback?: boolean;
19
27
  bluetoothEnabled?: boolean;
28
+ /** Protocol V2 only; changed through an on-device confirmation page. */
20
29
  airgapMode?: boolean;
30
+ /** Protocol V2 only. */
21
31
  animationEnabled?: boolean;
32
+ /** Protocol V2 only. */
22
33
  tapToWake?: boolean;
34
+ /** Protocol V2 only. */
23
35
  deviceNameDisplayEnabled?: boolean;
36
+ /** Protocol V2 only. */
24
37
  fidoEnabled?: boolean;
38
+ /** Protocol V2 only. */
25
39
  usbLockEnabled?: boolean;
40
+ /** Protocol V2 only. */
26
41
  randomKeypad?: boolean;
27
42
  };
28
43
 
@@ -1,4 +1,7 @@
1
- import type { Features } from '../device';
1
+ import type { DeviceState } from '../device';
2
2
  import type { CommonParams, Response } from '../params';
3
3
 
4
- export declare function deviceUnlock(connectId: string, params?: CommonParams): Response<Features>;
4
+ export declare function deviceUnlock(
5
+ connectId: string,
6
+ params?: CommonParams
7
+ ): Response<DeviceState>;
@@ -6,9 +6,6 @@ import type {
6
6
  deviceGetOnboardingStatus,
7
7
  deviceInfoGet,
8
8
  deviceReboot,
9
- deviceSettingsGet,
10
- deviceSettingsPageShow,
11
- deviceSettingsSet,
12
9
  deviceStatusGet,
13
10
  deviceUploadWallpaper,
14
11
  dirList,
@@ -183,7 +180,6 @@ export type CoreApi = {
183
180
  call: (params: any) => Promise<any>;
184
181
  uiResponse: typeof uiResponse;
185
182
  cancel: (connectId?: string) => void;
186
- cancelOperation: (operationId: string) => void;
187
183
  updateSettings: typeof updateSettings;
188
184
  switchTransport: (env: ConnectSettings['env']) => Promise<{ success: boolean }>;
189
185
  getLogs: typeof getLogs;
@@ -250,15 +246,12 @@ export type CoreApi = {
250
246
  deviceUploadWallpaper: typeof deviceUploadWallpaper;
251
247
  deviceInfoGet: typeof deviceInfoGet;
252
248
  deviceStatusGet: typeof deviceStatusGet;
253
- deviceSettingsGet: typeof deviceSettingsGet;
254
249
  protocolInfoRequest: typeof protocolInfoRequest;
255
250
  ping: typeof ping;
256
251
  deviceFirmwareUpdate: typeof deviceFirmwareUpdate;
257
252
  deviceGetFirmwareUpdateStatus: typeof deviceGetFirmwareUpdateStatus;
258
253
  deviceFactoryInfoSet: typeof deviceFactoryInfoSet;
259
254
  deviceFactoryInfoGet: typeof deviceFactoryInfoGet;
260
- deviceSettingsSet: typeof deviceSettingsSet;
261
- deviceSettingsPageShow: typeof deviceSettingsPageShow;
262
255
  filesystemPermissionFix: typeof filesystemPermissionFix;
263
256
  filesystemFormat: typeof filesystemFormat;
264
257
  uploadPortfolio: typeof uploadPortfolio;
@@ -3,7 +3,6 @@ import type {
3
3
  DevOnboardingStatus,
4
4
  DeviceFactoryInfo,
5
5
  DeviceFirmwareUpdateStatus,
6
- DeviceSettings,
7
6
  DeviceStatus,
8
7
  ProtocolInfo,
9
8
  ProtocolV2DeviceInfo,
@@ -16,8 +15,6 @@ import type {
16
15
  DeviceRebootParams,
17
16
  } from '../../api/protocol-v2/helpers';
18
17
  import type { DeviceInfoGetParams } from '../../api/protocol-v2/DeviceInfoGet';
19
- import type { DeviceSettingsSetParams } from '../../api/protocol-v2/DeviceSettingsSet';
20
- import type { DeviceSettingsPageShowParams } from '../../api/protocol-v2/DeviceSettingsPageShow';
21
18
  import type {
22
19
  DeviceUploadWallpaperParams,
23
20
  DeviceUploadWallpaperResponse,
@@ -37,11 +34,6 @@ export type {
37
34
  DeviceInfoGetTargets,
38
35
  DeviceInfoGetTypes,
39
36
  } from '../../api/protocol-v2/DeviceInfoGet';
40
- export type { DeviceSettingsSetParams } from '../../api/protocol-v2/DeviceSettingsSet';
41
- export type {
42
- DeviceSettingsPageShowParams,
43
- SupportedDeviceSettingsPage,
44
- } from '../../api/protocol-v2/DeviceSettingsPageShow';
45
37
  export type {
46
38
  DeviceUploadWallpaperParams,
47
39
  DeviceUploadWallpaperResponse,
@@ -98,12 +90,6 @@ export declare function deviceStatusGet(
98
90
  params?: CommonParams
99
91
  ): Response<DeviceStatus>;
100
92
 
101
- /** @deprecated Development-only raw Protocol V2 command. Use `getDeviceState`. */
102
- export declare function deviceSettingsGet(
103
- connectId: string,
104
- params?: CommonParams
105
- ): Response<DeviceSettings>;
106
-
107
93
  /** @deprecated Development-only raw Protocol V2 command. */
108
94
  export declare function protocolInfoRequest(
109
95
  connectId: string,
@@ -145,22 +131,6 @@ export declare function deviceFactoryInfoGet(
145
131
  params?: CommonParams
146
132
  ): Response<DeviceFactoryInfo>;
147
133
 
148
- /**
149
- * @deprecated Use the protocol-independent `deviceSettings`.
150
- */
151
- export declare function deviceSettingsSet(
152
- connectId: string,
153
- params: CommonParams & DeviceSettingsSetParams
154
- ): Response<Success>;
155
-
156
- /**
157
- * @deprecated Use `deviceSettings`, `deviceChangePin`, or `deviceWipe`.
158
- */
159
- export declare function deviceSettingsPageShow(
160
- connectId: string,
161
- params: CommonParams & DeviceSettingsPageShowParams
162
- ): Response<Success>;
163
-
164
134
  export declare function deviceUploadWallpaper(
165
135
  connectId: string,
166
136
  params: CommonParams & DeviceUploadWallpaperParams
@@ -226,7 +196,6 @@ export declare function pathInfo(
226
196
  export declare function uploadPortfolio(
227
197
  connectId: string,
228
198
  params: {
229
- operationId?: string;
230
199
  packageBytes: ArrayBuffer | Uint8Array | Blob;
231
200
  timeoutMs?: number | string;
232
201
  }
@@ -3,6 +3,7 @@ import { EDeviceType, type EFirmwareType } from '@onekeyfe/hd-shared';
3
3
  import type { IVersionArray } from './settings';
4
4
  import type { PROTO } from '../constants';
5
5
  import type {
6
+ Enum_SafetyCheckLevel,
6
7
  OneKeyDeviceCommType,
7
8
  ProtocolV2DeviceInfo,
8
9
  DeviceStatus as ProtocolV2DeviceStatus,
@@ -164,7 +165,8 @@ export type DeviceStateUpdateSource =
164
165
  | 'initialize'
165
166
  | 'device-info'
166
167
  | 'device-status'
167
- | 'apply-settings'
168
+ | 'settings-read'
169
+ | 'settings-write'
168
170
  | 'change-pin'
169
171
  | 'lock'
170
172
  | 'unlock'
@@ -207,7 +209,7 @@ export type DeviceStateSettings = {
207
209
  sdProtection: boolean | null;
208
210
  wipeCodeProtection: boolean | null;
209
211
  passphraseAlwaysOnDevice: boolean | null;
210
- safetyChecks: string | null;
212
+ safetyChecks: Enum_SafetyCheckLevel | null;
211
213
  autoLockDelayMs: number | null;
212
214
  autoShutdownDelayMs: number | null;
213
215
  displayRotation: number | null;
@@ -306,7 +308,7 @@ export type NormalizedFeatures = {
306
308
  wipeCodeProtection: boolean | null;
307
309
  passphraseAlwaysOnDevice: boolean | null;
308
310
  attachToPinEnabled?: boolean | null;
309
- safetyChecks: string | null;
311
+ safetyChecks: Enum_SafetyCheckLevel | null;
310
312
  autoLockDelayMs: number | null;
311
313
  autoShutdownDelayMs: number | null;
312
314
  displayRotation: number | null;
@@ -1,6 +1,52 @@
1
1
  import { EDeviceType } from '@onekeyfe/hd-shared';
2
+ import { Enum_SafetyCheckLevel } from '@onekeyfe/hd-transport';
2
3
 
3
4
  import type { IDeviceType } from '../types';
5
+ import type { DeviceSettingsParams } from '../types/api/deviceSettings';
6
+ import type { SafetyCheckLevel } from '@onekeyfe/hd-transport';
7
+
8
+ export type DeviceSettingsProtocol = 'V1' | 'V2';
9
+ export type DeviceSettingsField = keyof DeviceSettingsParams;
10
+
11
+ export const DEVICE_SETTINGS_SHARED_FIELDS = [
12
+ 'language',
13
+ 'label',
14
+ 'usePassphrase',
15
+ 'autoLockDelayMs',
16
+ 'autoShutdownDelayMs',
17
+ 'hapticFeedback',
18
+ 'bluetoothEnabled',
19
+ ] as const satisfies readonly DeviceSettingsField[];
20
+
21
+ export const DEVICE_SETTINGS_V1_ONLY_FIELDS = [
22
+ 'homescreen',
23
+ 'passphraseSource',
24
+ 'displayRotation',
25
+ 'passphraseAlwaysOnDevice',
26
+ 'safetyChecks',
27
+ 'experimentalFeatures',
28
+ 'changeBrightness',
29
+ ] as const satisfies readonly DeviceSettingsField[];
30
+
31
+ export const DEVICE_SETTINGS_V2_ONLY_FIELDS = [
32
+ 'brightness',
33
+ 'airgapMode',
34
+ 'animationEnabled',
35
+ 'tapToWake',
36
+ 'deviceNameDisplayEnabled',
37
+ 'fidoEnabled',
38
+ 'usbLockEnabled',
39
+ 'randomKeypad',
40
+ ] as const satisfies readonly DeviceSettingsField[];
41
+
42
+ export const PROTOCOL_V2_NEVER_TIMEOUT_MS = 0x10000000;
43
+
44
+ export const normalizeSafetyCheckLevel = (
45
+ value: SafetyCheckLevel | null | undefined
46
+ ): Enum_SafetyCheckLevel | null | undefined => {
47
+ if (typeof value === 'number' || value === null || value === undefined) return value;
48
+ return Enum_SafetyCheckLevel[value];
49
+ };
4
50
 
5
51
  export const LANGUAGE_LABELS = {
6
52
  en: 'English',
@@ -36,6 +82,13 @@ export const PROTOCOL_V2_LANGUAGE_BY_KEY: Record<LanguageKey, string> = {
36
82
  export const mapLanguageToProtocolV2 = (language?: string) =>
37
83
  language ? PROTOCOL_V2_LANGUAGE_BY_KEY[language as LanguageKey] ?? language : undefined;
38
84
 
85
+ const PROTOCOL_V2_LANGUAGE_KEY_BY_TAG = Object.fromEntries(
86
+ Object.entries(PROTOCOL_V2_LANGUAGE_BY_KEY).map(([key, tag]) => [tag, key])
87
+ ) as Record<string, LanguageKey>;
88
+
89
+ export const mapLanguageFromProtocolV2 = (language?: string) =>
90
+ language ? PROTOCOL_V2_LANGUAGE_KEY_BY_TAG[language] ?? language : undefined;
91
+
39
92
  const PRO2_LANGUAGE_OPTIONS = [
40
93
  ...Object.entries(LANGUAGE_LABELS).map(([code, label]) => ({ code, label })),
41
94
  { code: 'zh-Hant-TW', label: '繁體中文(台灣)' },
@@ -73,85 +126,106 @@ export const getLanguageConfig = (deviceType: IDeviceType): Record<string, strin
73
126
  return keys.map(key => ({ code: key, label: LANGUAGE_LABELS[key] }));
74
127
  };
75
128
 
76
- export type DurationParts = {
77
- seconds: number;
78
- minute: number;
79
- hour: number;
80
- day: number;
129
+ export type DeviceSettingsDurationOption = {
130
+ label: string;
131
+ valueMs: number;
132
+ };
133
+
134
+ export type DeviceSettingsValueOption<T> = {
135
+ label: string;
136
+ value: T;
81
137
  };
82
138
 
83
- export const getAutoLockOptions = (_deviceType: IDeviceType): DurationParts[] => {
84
- switch (_deviceType) {
139
+ const durationOption = (valueMs: number): DeviceSettingsDurationOption => {
140
+ if (valueMs === 0 || valueMs === PROTOCOL_V2_NEVER_TIMEOUT_MS) {
141
+ return { label: 'Never', valueMs };
142
+ }
143
+ if (valueMs < 60_000) {
144
+ return { label: `${valueMs / 1000} seconds`, valueMs };
145
+ }
146
+ const minutes = valueMs / 60_000;
147
+ return { label: `${minutes} ${minutes === 1 ? 'minute' : 'minutes'}`, valueMs };
148
+ };
149
+
150
+ const withNever = (
151
+ values: readonly number[],
152
+ protocol: DeviceSettingsProtocol
153
+ ): DeviceSettingsDurationOption[] =>
154
+ [...values, protocol === 'V2' ? PROTOCOL_V2_NEVER_TIMEOUT_MS : 0].map(durationOption);
155
+
156
+ export const getAutoLockOptions = (
157
+ deviceType: IDeviceType,
158
+ protocol: DeviceSettingsProtocol
159
+ ): DeviceSettingsDurationOption[] => {
160
+ switch (deviceType) {
85
161
  case EDeviceType.Mini:
86
162
  case EDeviceType.Classic:
87
163
  case EDeviceType.Classic1s:
88
164
  case EDeviceType.ClassicPure:
89
- return [
90
- { seconds: 0, minute: 1, hour: 0, day: 0 },
91
- { seconds: 0, minute: 2, hour: 0, day: 0 },
92
- { seconds: 0, minute: 5, hour: 0, day: 0 },
93
- { seconds: 0, minute: 10, hour: 0, day: 0 },
94
- { seconds: 0, minute: 0, hour: 0, day: 0 },
95
- ];
165
+ return withNever([60_000, 120_000, 300_000, 600_000], protocol);
96
166
  case EDeviceType.Touch:
97
167
  case EDeviceType.Pro:
98
- return [
99
- { seconds: 30, minute: 0, hour: 0, day: 0 },
100
- { seconds: 0, minute: 1, hour: 0, day: 0 },
101
- { seconds: 0, minute: 2, hour: 0, day: 0 },
102
- { seconds: 0, minute: 5, hour: 0, day: 0 },
103
- { seconds: 0, minute: 10, hour: 0, day: 0 },
104
- { seconds: 0, minute: 30, hour: 0, day: 0 },
105
- { seconds: 0, minute: 0, hour: 0, day: 0 },
106
- ];
107
168
  case EDeviceType.Pro2:
108
- return [
109
- { seconds: 30, minute: 0, hour: 0, day: 0 },
110
- { seconds: 0, minute: 1, hour: 0, day: 0 },
111
- { seconds: 0, minute: 2, hour: 0, day: 0 },
112
- { seconds: 0, minute: 5, hour: 0, day: 0 },
113
- { seconds: 0, minute: 10, hour: 0, day: 0 },
114
- { seconds: 0, minute: 30, hour: 0, day: 0 },
115
- { seconds: 0, minute: 0, hour: 0, day: 0 },
116
- ];
169
+ return withNever([30_000, 60_000, 120_000, 300_000, 600_000, 1_800_000], protocol);
117
170
  default:
118
171
  return [];
119
172
  }
120
173
  };
121
174
 
122
- export const getAutoShutDownOptions = (_deviceType: IDeviceType): DurationParts[] => {
123
- switch (_deviceType) {
175
+ export const getAutoShutDownOptions = (
176
+ deviceType: IDeviceType,
177
+ protocol: DeviceSettingsProtocol
178
+ ): DeviceSettingsDurationOption[] => {
179
+ switch (deviceType) {
124
180
  case EDeviceType.Mini:
125
181
  return [];
126
182
  case EDeviceType.Classic:
127
183
  case EDeviceType.Classic1s:
128
184
  case EDeviceType.ClassicPure:
129
- return [
130
- { seconds: 0, minute: 1, hour: 0, day: 0 },
131
- { seconds: 0, minute: 3, hour: 0, day: 0 },
132
- { seconds: 0, minute: 5, hour: 0, day: 0 },
133
- { seconds: 0, minute: 10, hour: 0, day: 0 },
134
- { seconds: 0, minute: 0, hour: 0, day: 0 },
135
- ];
185
+ return withNever([60_000, 180_000, 300_000, 600_000], protocol);
136
186
  case EDeviceType.Touch:
137
187
  case EDeviceType.Pro:
138
- return [
139
- { seconds: 0, minute: 1, hour: 0, day: 0 },
140
- { seconds: 0, minute: 2, hour: 0, day: 0 },
141
- { seconds: 0, minute: 5, hour: 0, day: 0 },
142
- { seconds: 0, minute: 10, hour: 0, day: 0 },
143
- { seconds: 0, minute: 0, hour: 0, day: 0 },
144
- ];
188
+ return withNever([60_000, 120_000, 300_000, 600_000], protocol);
145
189
  case EDeviceType.Pro2:
146
- return [
147
- { seconds: 0, minute: 1, hour: 0, day: 0 },
148
- { seconds: 0, minute: 2, hour: 0, day: 0 },
149
- { seconds: 0, minute: 5, hour: 0, day: 0 },
150
- { seconds: 0, minute: 10, hour: 0, day: 0 },
151
- { seconds: 0, minute: 30, hour: 0, day: 0 },
152
- { seconds: 0, minute: 0, hour: 0, day: 0 },
153
- ];
190
+ return withNever([60_000, 120_000, 300_000, 600_000, 1_800_000], protocol);
154
191
  default:
155
192
  return [];
156
193
  }
157
194
  };
195
+
196
+ export type DeviceSettingsCapabilities = {
197
+ protocol: DeviceSettingsProtocol;
198
+ supportedFields: readonly DeviceSettingsField[];
199
+ languageOptions: ReadonlyArray<Record<string, string>>;
200
+ autoLockDelayOptions: readonly DeviceSettingsDurationOption[];
201
+ autoShutdownDelayOptions: readonly DeviceSettingsDurationOption[];
202
+ ranges: {
203
+ brightness?: { min: number; max: number };
204
+ };
205
+ safetyCheckOptions: ReadonlyArray<DeviceSettingsValueOption<Enum_SafetyCheckLevel>>;
206
+ onDeviceConfirmationFields: readonly DeviceSettingsField[];
207
+ };
208
+
209
+ export const getDeviceSettingsCapabilities = (
210
+ deviceType: IDeviceType,
211
+ protocol: DeviceSettingsProtocol
212
+ ): DeviceSettingsCapabilities => ({
213
+ protocol,
214
+ supportedFields:
215
+ protocol === 'V2'
216
+ ? [...DEVICE_SETTINGS_SHARED_FIELDS, ...DEVICE_SETTINGS_V2_ONLY_FIELDS]
217
+ : [...DEVICE_SETTINGS_SHARED_FIELDS, ...DEVICE_SETTINGS_V1_ONLY_FIELDS],
218
+ languageOptions: getLanguageConfig(deviceType),
219
+ autoLockDelayOptions: getAutoLockOptions(deviceType, protocol),
220
+ autoShutdownDelayOptions: getAutoShutDownOptions(deviceType, protocol),
221
+ ranges: protocol === 'V2' ? { brightness: { min: 10, max: 100 } } : {},
222
+ safetyCheckOptions:
223
+ protocol === 'V1'
224
+ ? [
225
+ { label: 'Strict', value: Enum_SafetyCheckLevel.Strict },
226
+ { label: 'Prompt Always', value: Enum_SafetyCheckLevel.PromptAlways },
227
+ { label: 'Prompt Temporarily', value: Enum_SafetyCheckLevel.PromptTemporarily },
228
+ ]
229
+ : [],
230
+ onDeviceConfirmationFields: protocol === 'V2' ? ['usePassphrase', 'airgapMode'] : [],
231
+ });
@@ -30,7 +30,24 @@ export {
30
30
  checkNeedUpdateBootForTouch,
31
31
  checkNeedUpdateBootForClassicAndMini,
32
32
  } from '../api/firmware/updateBootloader';
33
- export { getLanguageConfig, getAutoLockOptions, getAutoShutDownOptions } from './deviceSettings';
33
+ export {
34
+ DEVICE_SETTINGS_SHARED_FIELDS,
35
+ DEVICE_SETTINGS_V1_ONLY_FIELDS,
36
+ DEVICE_SETTINGS_V2_ONLY_FIELDS,
37
+ PROTOCOL_V2_NEVER_TIMEOUT_MS,
38
+ getAutoLockOptions,
39
+ getAutoShutDownOptions,
40
+ getDeviceSettingsCapabilities,
41
+ getLanguageConfig,
42
+ normalizeSafetyCheckLevel,
43
+ } from './deviceSettings';
44
+ export type {
45
+ DeviceSettingsCapabilities,
46
+ DeviceSettingsDurationOption,
47
+ DeviceSettingsField,
48
+ DeviceSettingsProtocol,
49
+ DeviceSettingsValueOption,
50
+ } from './deviceSettings';
34
51
 
35
52
  // Helpers utils
36
53
 
@@ -1,140 +0,0 @@
1
- import RequestQueue from '../src/core/RequestQueue';
2
-
3
- import type { BaseMethod } from '../src/api/BaseMethod';
4
-
5
- jest.mock('../src/data/config', () => ({
6
- getSDKVersion: jest.fn(() => '1.0.0'),
7
- DEFAULT_DOMAIN: 'https://jssdk.onekey.so/1.0.0/',
8
- }));
9
-
10
- function buildMethod(responseID: number, operationId?: string) {
11
- return {
12
- connectId: 'device-1',
13
- executionPriority: 'normal',
14
- payload: { operationId },
15
- responseID,
16
- } as unknown as BaseMethod;
17
- }
18
-
19
- function buildBackgroundMethod(responseID: number, operationId?: string) {
20
- return {
21
- ...buildMethod(responseID, operationId),
22
- executionPriority: 'background',
23
- } as unknown as BaseMethod;
24
- }
25
-
26
- describe('RequestQueue operation cancellation', () => {
27
- test('aborts only the request matching the operation id', () => {
28
- const queue = new RequestQueue();
29
- const portfolio = queue.createTask(buildMethod(1, 'portfolio-1'));
30
- const userAction = queue.createTask(buildMethod(2, 'user-action'));
31
-
32
- expect(queue.abortOperation('portfolio-1')).toBe(true);
33
- expect(portfolio.abortController?.signal.aborted).toBe(true);
34
- expect(userAction.abortController?.signal.aborted).toBe(false);
35
- });
36
-
37
- test('returns false for an unknown operation id', () => {
38
- const queue = new RequestQueue();
39
- queue.createTask(buildMethod(1, 'portfolio-1'));
40
-
41
- expect(queue.abortOperation('missing')).toBe(false);
42
- });
43
-
44
- test('honors cancellation that arrives before the request is registered', () => {
45
- const queue = new RequestQueue();
46
-
47
- expect(queue.abortOperation('portfolio-1')).toBe(false);
48
-
49
- const portfolio = queue.createTask(buildMethod(1, 'portfolio-1'));
50
- const userAction = queue.createTask(buildMethod(2, 'user-action'));
51
-
52
- expect(portfolio.abortController?.signal.aborted).toBe(true);
53
- expect(userAction.abortController?.signal.aborted).toBe(false);
54
- });
55
-
56
- test('expires a cancellation that is never matched', () => {
57
- const nowSpy = jest.spyOn(Date, 'now');
58
- nowSpy.mockReturnValueOnce(1_000);
59
- const queue = new RequestQueue();
60
- queue.abortOperation('portfolio-1');
61
- nowSpy.mockReturnValue(31_001);
62
-
63
- const portfolio = queue.createTask(buildMethod(1, 'portfolio-1'));
64
-
65
- expect(portfolio.abortController?.signal.aborted).toBe(false);
66
- nowSpy.mockRestore();
67
- });
68
-
69
- test('rejects a background request while the device has an active user request', async () => {
70
- const queue = new RequestQueue();
71
- queue.createTask(buildMethod(1, 'user-action'));
72
-
73
- await expect(
74
- queue.admitTask(buildBackgroundMethod(2, 'portfolio-1'), {
75
- backgroundPreemptTimeoutMs: 100,
76
- })
77
- ).resolves.toMatchObject({ status: 'busy' });
78
- expect(queue.getTask(2)).toBeUndefined();
79
- });
80
-
81
- test('aborts and waits for an active background request before admitting a user request', async () => {
82
- const queue = new RequestQueue();
83
- const portfolio = queue.createTask(buildBackgroundMethod(1, 'portfolio-1'));
84
-
85
- const admission = queue.admitTask(buildMethod(2, 'user-action'), {
86
- backgroundPreemptTimeoutMs: 100,
87
- });
88
- await Promise.resolve();
89
-
90
- expect(portfolio.abortController?.signal.aborted).toBe(true);
91
- expect(queue.getTask(2)).toBeUndefined();
92
-
93
- portfolio.settled.resolve();
94
- await Promise.resolve();
95
- expect(queue.getTask(2)).toBeUndefined();
96
-
97
- queue.releaseTask(1);
98
-
99
- await expect(admission).resolves.toMatchObject({
100
- status: 'reserved',
101
- task: { id: 2 },
102
- });
103
- });
104
-
105
- test('uses the background method abort latency when no admission override is provided', async () => {
106
- const queue = new RequestQueue();
107
- const portfolio = queue.createTask(buildBackgroundMethod(1, 'portfolio-1'));
108
- portfolio.method.maxAbortLatencyMs = 12_000;
109
- const waitForTasksReleased = jest
110
- .spyOn(queue as any, 'waitForTasksReleased')
111
- .mockResolvedValue(false);
112
-
113
- await expect(queue.admitTask(buildMethod(2, 'user-action'))).resolves.toMatchObject({
114
- status: 'busy',
115
- });
116
- expect(waitForTasksReleased).toHaveBeenCalledWith([portfolio], 12_000);
117
- });
118
-
119
- test('returns busy when an aborted background request does not release in time', async () => {
120
- const queue = new RequestQueue();
121
- const portfolio = queue.createTask(buildBackgroundMethod(1, 'portfolio-1'));
122
-
123
- await expect(
124
- queue.admitTask(buildMethod(2, 'user-action'), {
125
- backgroundPreemptTimeoutMs: 1,
126
- })
127
- ).resolves.toMatchObject({
128
- status: 'busy',
129
- blockingTask: { id: 1 },
130
- });
131
- expect(portfolio.abortController?.signal.aborted).toBe(true);
132
- expect(queue.getTask(2)).toBeUndefined();
133
-
134
- queue.releaseTask(1);
135
- await expect(queue.admitTask(buildMethod(3, 'user-retry'))).resolves.toMatchObject({
136
- status: 'reserved',
137
- task: { id: 3 },
138
- });
139
- });
140
- });
@@ -1,46 +0,0 @@
1
- import UploadPortfolio from '../src/api/UploadPortfolio';
2
-
3
- jest.mock('../src/data/config', () => ({
4
- getSDKVersion: jest.fn(() => '1.0.0'),
5
- DEFAULT_DOMAIN: 'https://jssdk.onekey.so/1.0.0/',
6
- }));
7
-
8
- describe('UploadPortfolio timeout', () => {
9
- test('applies the command timeout to staging and PortfolioUpdate', async () => {
10
- const packageBytes = new Uint8Array([1, 2, 3]);
11
- const typedCall = jest
12
- .fn()
13
- .mockResolvedValueOnce({ message: { processed_byte: 3 } })
14
- .mockResolvedValueOnce({ message: {} });
15
- const method = new UploadPortfolio({
16
- id: 1,
17
- payload: {
18
- method: 'uploadPortfolio',
19
- packageBytes,
20
- },
21
- });
22
- method.device = {
23
- commands: { typedCall },
24
- } as any;
25
- method.postMessage = jest.fn();
26
-
27
- method.init();
28
- await method.run();
29
-
30
- expect(method.executionPriority).toBe('background');
31
- expect(typedCall).toHaveBeenNthCalledWith(
32
- 1,
33
- 'FilesystemFileWrite',
34
- 'FilesystemFile',
35
- expect.any(Object),
36
- { timeoutMs: 5_000 }
37
- );
38
- expect(typedCall).toHaveBeenNthCalledWith(
39
- 2,
40
- 'PortfolioUpdate',
41
- 'Success',
42
- {},
43
- { timeoutMs: 5_000 }
44
- );
45
- });
46
- });
@@ -1,6 +0,0 @@
1
- import { BaseMethod } from '../BaseMethod';
2
- export default class DeviceSettingsGet extends BaseMethod {
3
- init(): void;
4
- run(): Promise<import("packages/hd-transport/dist").DeviceSettings>;
5
- }
6
- //# sourceMappingURL=DeviceSettingsGet.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DeviceSettingsGet.d.ts","sourceRoot":"","sources":["../../../src/api/protocol-v2/DeviceSettingsGet.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAG3C,MAAM,CAAC,OAAO,OAAO,iBAAkB,SAAQ,UAAU;IACvD,IAAI;IAQE,GAAG;CAKV"}
@@ -1,16 +0,0 @@
1
- import { DeviceSettingsPage } from '@onekeyfe/hd-transport';
2
- import { BaseMethod } from '../BaseMethod';
3
- export type SupportedDeviceSettingsPage = DeviceSettingsPage;
4
- export type DeviceSettingsPageShowParams = {
5
- page?: SupportedDeviceSettingsPage | 'DeviceReset' | 'DevicePinChange' | 'DevicePassphrase' | 'DeviceAirgap';
6
- fieldName?: string;
7
- field_name?: string;
8
- };
9
- export default class DeviceSettingsPageShow extends BaseMethod<{
10
- page: SupportedDeviceSettingsPage;
11
- field_name?: string;
12
- }> {
13
- init(): void;
14
- run(): Promise<import("@onekeyfe/hd-transport").Success>;
15
- }
16
- //# sourceMappingURL=DeviceSettingsPageShow.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DeviceSettingsPageShow.d.ts","sourceRoot":"","sources":["../../../src/api/protocol-v2/DeviceSettingsPageShow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAE5D,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAI3C,MAAM,MAAM,2BAA2B,GAAG,kBAAkB,CAAC;AAE7D,MAAM,MAAM,4BAA4B,GAAG;IACzC,IAAI,CAAC,EACD,2BAA2B,GAC3B,aAAa,GACb,iBAAiB,GACjB,kBAAkB,GAClB,cAAc,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAmBF,MAAM,CAAC,OAAO,OAAO,sBAAuB,SAAQ,UAAU,CAAC;IAC7D,IAAI,EAAE,2BAA2B,CAAC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;IACA,IAAI;IAgBE,GAAG;CAaV"}