@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
@@ -10,11 +10,56 @@ import {
10
10
  mapDeviceSettingsToState,
11
11
  } from '../../device/DeviceStateMapper';
12
12
  import { getProtocolV2SettingsBehavior } from '../../protocols/protocol-v2/settingsUnlockPolicy';
13
- import { LANGUAGE_LABELS } from '../../utils/deviceSettings';
13
+ import {
14
+ DEVICE_SETTINGS_V1_ONLY_FIELDS,
15
+ DEVICE_SETTINGS_V2_ONLY_FIELDS,
16
+ LANGUAGE_LABELS,
17
+ getDeviceSettingsCapabilities,
18
+ } from '../../utils/deviceSettings';
14
19
 
15
20
  import type { ApplySettings } from '@onekeyfe/hd-transport';
16
21
  import type { DeviceSettingsParams } from '../../types/api/deviceSettings';
17
22
 
23
+ const assertSettingsSupported = (
24
+ payload: DeviceSettingsParams,
25
+ unsupported: readonly (keyof DeviceSettingsParams)[],
26
+ protocol: 'Protocol V1' | 'Protocol V2'
27
+ ) => {
28
+ const provided = unsupported.filter(key => payload[key] !== undefined);
29
+ if (provided.length > 0) {
30
+ throw invalidParameter(`${protocol} does not support settings: ${provided.join(', ')}.`);
31
+ }
32
+ };
33
+
34
+ const assertProtocolV2SettingValues = (
35
+ payload: DeviceSettingsParams,
36
+ capabilities: ReturnType<typeof getDeviceSettingsCapabilities>
37
+ ) => {
38
+ const brightnessRange = capabilities.ranges.brightness;
39
+ if (
40
+ payload.brightness !== undefined &&
41
+ brightnessRange &&
42
+ (payload.brightness < brightnessRange.min || payload.brightness > brightnessRange.max)
43
+ ) {
44
+ throw invalidParameter(
45
+ `Protocol V2 brightness must be between ${brightnessRange.min} and ${brightnessRange.max}.`
46
+ );
47
+ }
48
+
49
+ const delayFields = [
50
+ ['autoLockDelayMs', capabilities.autoLockDelayOptions],
51
+ ['autoShutdownDelayMs', capabilities.autoShutdownDelayOptions],
52
+ ] as const;
53
+ delayFields.forEach(([field, options]) => {
54
+ const value = payload[field];
55
+ if (value !== undefined && !options.some(option => option.valueMs === value)) {
56
+ throw invalidParameter(
57
+ `Protocol V2 ${field} must be one of: ${options.map(option => option.valueMs).join(', ')}.`
58
+ );
59
+ }
60
+ });
61
+ };
62
+
18
63
  const settingsPageForPayload = (
19
64
  payload: DeviceSettingsParams
20
65
  ): DeviceSettingsPage.DevicePassphrase | DeviceSettingsPage.DeviceAirgap | undefined => {
@@ -70,6 +115,7 @@ export default class DeviceSettings extends BaseMethod<ApplySettings> {
70
115
  safety_checks: this.payload.safetyChecks,
71
116
  experimental_features: this.payload.experimentalFeatures,
72
117
  auto_shutdown_delay_ms: this.payload.autoShutdownDelayMs,
118
+ use_ble: this.payload.bluetoothEnabled,
73
119
  ...(this.payload.changeBrightness
74
120
  ? { change_brightness: this.payload.changeBrightness }
75
121
  : undefined),
@@ -113,6 +159,12 @@ export default class DeviceSettings extends BaseMethod<ApplySettings> {
113
159
  async run() {
114
160
  try {
115
161
  if (this.device.isProtocolV2()) {
162
+ assertSettingsSupported(this.payload, DEVICE_SETTINGS_V1_ONLY_FIELDS, 'Protocol V2');
163
+ const capabilities = getDeviceSettingsCapabilities(
164
+ this.device.getCurrentDeviceType(),
165
+ 'V2'
166
+ );
167
+ assertProtocolV2SettingValues(this.payload, capabilities);
116
168
  const settings = mapCommonSettingsToProtocolV2(this.payload);
117
169
  const requestedPassphrase = this.payload.usePassphrase;
118
170
  const requestedAirgap = this.payload.airgapMode;
@@ -172,18 +224,27 @@ export default class DeviceSettings extends BaseMethod<ApplySettings> {
172
224
  const res = await this.device.commands.typedCall('DeviceSettingsSet', 'Success', {
173
225
  settings,
174
226
  });
175
- this.device.updateState(mapDeviceSettingsToState(settings), 'apply-settings');
227
+ this.device.updateState(mapDeviceSettingsToState(settings), 'settings-write');
176
228
  return res.message;
177
229
  }
178
230
 
179
- if (this.payload.airgapMode !== undefined) {
180
- throw invalidParameter('Air-gap settings are not supported by Protocol V1.');
231
+ assertSettingsSupported(this.payload, DEVICE_SETTINGS_V2_ONLY_FIELDS, 'Protocol V1');
232
+ const capabilities = getDeviceSettingsCapabilities(this.device.getCurrentDeviceType(), 'V1');
233
+ if (
234
+ this.payload.safetyChecks !== undefined &&
235
+ !capabilities.safetyCheckOptions.some(option => option.value === this.payload.safetyChecks)
236
+ ) {
237
+ throw invalidParameter(
238
+ `Protocol V1 safetyChecks must be one of: ${capabilities.safetyCheckOptions
239
+ .map(option => option.value)
240
+ .join(', ')}.`
241
+ );
181
242
  }
182
243
 
183
244
  const res = await this.device.commands.typedCall('ApplySettings', 'Success', {
184
245
  ...this.params,
185
246
  });
186
- this.device.updateState(mapApplySettingsToState(this.params), 'apply-settings');
247
+ this.device.updateState(mapApplySettingsToState(this.params), 'settings-write');
187
248
  return res.message;
188
249
  } catch (error) {
189
250
  if (error.message?.toLowerCase().includes('no setting provided')) {
@@ -17,6 +17,7 @@ export default class DeviceUnlock extends BaseMethod<LockDevice> {
17
17
  }
18
18
 
19
19
  async run() {
20
- return this.device.unlockDevice();
20
+ await this.device.unlockDevice();
21
+ return this.device.getDeviceState();
21
22
  }
22
23
  }
package/src/api/index.ts CHANGED
@@ -51,15 +51,12 @@ export { default as deviceUploadWallpaper } from './protocol-v2/DeviceUploadWall
51
51
  // Protocol V2 development APIs. These remain public while Pro2 integration is in development.
52
52
  export { default as deviceInfoGet } from './protocol-v2/DeviceInfoGet';
53
53
  export { default as deviceStatusGet } from './protocol-v2/DeviceStatusGet';
54
- export { default as deviceSettingsGet } from './protocol-v2/DeviceSettingsGet';
55
54
  export { default as protocolInfoRequest } from './protocol-v2/ProtocolInfoRequest';
56
55
  export { default as ping } from './protocol-v2/Ping';
57
56
  export { default as deviceFirmwareUpdate } from './protocol-v2/DeviceFirmwareUpdate';
58
57
  export { default as deviceGetFirmwareUpdateStatus } from './protocol-v2/DeviceGetFirmwareUpdateStatus';
59
58
  export { default as deviceFactoryInfoSet } from './protocol-v2/DeviceFactoryInfoSet';
60
59
  export { default as deviceFactoryInfoGet } from './protocol-v2/DeviceFactoryInfoGet';
61
- export { default as deviceSettingsSet } from './protocol-v2/DeviceSettingsSet';
62
- export { default as deviceSettingsPageShow } from './protocol-v2/DeviceSettingsPageShow';
63
60
  export { default as filesystemPermissionFix } from './protocol-v2/FilesystemPermissionFix';
64
61
  export { default as filesystemFormat } from './protocol-v2/FilesystemFormat';
65
62
  export { default as fileRead } from './FileRead';
@@ -1,47 +1,21 @@
1
- import { type Deferred, createDeferred } from '@onekeyfe/hd-shared';
2
-
3
1
  import { LoggerNames, getLogger } from '../utils';
4
2
 
3
+ import type { Deferred } from '@onekeyfe/hd-shared';
5
4
  import type { BaseMethod } from '../api/BaseMethod';
6
5
 
7
6
  const Log = getLogger(LoggerNames.Core);
8
- const OPERATION_PRE_CANCEL_TTL_MS = 30_000;
9
- const DEFAULT_BACKGROUND_PREEMPT_TIMEOUT_MS = 5_500;
10
-
11
7
  export type RequestTask = {
12
8
  id: number;
13
9
  method: BaseMethod;
14
10
  callPromise?: Deferred<any> | undefined;
15
11
  abortController?: AbortController;
16
- settled: Deferred<void>;
17
- released: Deferred<void>;
18
- };
19
-
20
- export type RequestAdmission =
21
- | { status: 'reserved'; task: RequestTask }
22
- | { status: 'busy'; blockingTask?: RequestTask };
23
-
24
- export type RequestAdmissionOptions = {
25
- backgroundPreemptTimeoutMs?: number;
26
12
  };
27
13
 
28
14
  export default class RequestQueue {
29
15
  private requestQueue = new Map<number, RequestTask>();
30
16
 
31
- private operationRequestIds = new Map<string, number>();
32
-
33
- private pendingOperationCancellations = new Map<string, number>();
34
-
35
17
  private pendingCallbackTasks = new Map<string, Deferred<void>>();
36
18
 
37
- private prunePendingOperationCancellations(now = Date.now()) {
38
- this.pendingOperationCancellations.forEach((expiresAt, operationId) => {
39
- if (expiresAt <= now) {
40
- this.pendingOperationCancellations.delete(operationId);
41
- }
42
- });
43
- }
44
-
45
19
  // 生成唯一请求ID
46
20
  public generateRequestId = (method?: BaseMethod) => {
47
21
  if (method && method.responseID != null) {
@@ -57,93 +31,11 @@ export default class RequestQueue {
57
31
  }
58
32
  const abortController = new AbortController();
59
33
  method.abortSignal = abortController.signal;
60
- const task = {
61
- id: requestId,
62
- method,
63
- abortController,
64
- settled: createDeferred<void>(),
65
- released: createDeferred<void>(),
66
- };
34
+ const task = { id: requestId, method, abortController };
67
35
  this.requestQueue.set(requestId, task);
68
- const operationId = method.payload?.operationId;
69
- if (typeof operationId === 'string' && operationId) {
70
- this.operationRequestIds.set(operationId, requestId);
71
- this.prunePendingOperationCancellations();
72
- if (this.pendingOperationCancellations.delete(operationId)) {
73
- abortController.abort();
74
- }
75
- }
76
36
  return task;
77
37
  }
78
38
 
79
- public async admitTask(
80
- method: BaseMethod,
81
- options: RequestAdmissionOptions = {}
82
- ): Promise<RequestAdmission> {
83
- const activeTasks = Array.from(this.requestQueue.values()).filter(
84
- task => task.method.connectId === method.connectId
85
- );
86
-
87
- if (method.executionPriority === 'background') {
88
- if (activeTasks.length) {
89
- Log.debug(
90
- `Reject background method ${method.name}: device is occupied by ${activeTasks[0].method.name}`
91
- );
92
- return { status: 'busy', blockingTask: activeTasks[0] };
93
- }
94
- return { status: 'reserved', task: this.createTask(method) };
95
- }
96
-
97
- const backgroundTasks = activeTasks.filter(
98
- task => task.method.executionPriority === 'background'
99
- );
100
- if (!backgroundTasks.length) {
101
- return { status: 'reserved', task: this.createTask(method) };
102
- }
103
-
104
- Log.debug(
105
- `Preempt ${backgroundTasks.length} background request(s) for user method ${method.name}`
106
- );
107
- backgroundTasks.forEach(task => task.abortController?.abort());
108
- const timeoutMs =
109
- options.backgroundPreemptTimeoutMs ??
110
- Math.max(
111
- DEFAULT_BACKGROUND_PREEMPT_TIMEOUT_MS,
112
- ...backgroundTasks.map(task => task.method.maxAbortLatencyMs ?? 0)
113
- );
114
- const released = await this.waitForTasksReleased(backgroundTasks, timeoutMs);
115
- if (!released) {
116
- Log.warn(`Background request cleanup timed out before user method ${method.name}`);
117
- return { status: 'busy', blockingTask: backgroundTasks[0] };
118
- }
119
-
120
- return { status: 'reserved', task: this.createTask(method) };
121
- }
122
-
123
- private async waitForTasksReleased(tasks: RequestTask[], timeoutMs: number) {
124
- let timer: ReturnType<typeof setTimeout> | undefined;
125
- const timeoutPromise = new Promise<false>(resolve => {
126
- timer = setTimeout(() => resolve(false), timeoutMs);
127
- });
128
- const releasedPromise = Promise.all(tasks.map(task => task.released.promise)).then(() => true);
129
- const released = await Promise.race([releasedPromise, timeoutPromise]);
130
- if (timer) {
131
- clearTimeout(timer);
132
- }
133
- return released;
134
- }
135
-
136
- public abortOperation(operationId: string) {
137
- const requestId = this.operationRequestIds.get(operationId);
138
- if (requestId !== undefined) {
139
- return this.abortRequest(requestId);
140
- }
141
- const now = Date.now();
142
- this.prunePendingOperationCancellations(now);
143
- this.pendingOperationCancellations.set(operationId, now + OPERATION_PRE_CANCEL_TTL_MS);
144
- return false;
145
- }
146
-
147
39
  public getTask(requestId: number): RequestTask | undefined {
148
40
  return this.requestQueue.get(requestId);
149
41
  }
@@ -186,7 +78,6 @@ export default class RequestQueue {
186
78
  count++;
187
79
  }
188
80
  });
189
- this.pendingOperationCancellations.clear();
190
81
  return count;
191
82
  }
192
83
 
@@ -200,8 +91,8 @@ export default class RequestQueue {
200
91
  const request = this.requestQueue.get(requestId);
201
92
  if (request) {
202
93
  request.callPromise?.resolve(response);
203
- request.settled.resolve();
204
94
  }
95
+ this.releaseTask(requestId);
205
96
  }
206
97
 
207
98
  // 拒绝请求
@@ -209,22 +100,12 @@ export default class RequestQueue {
209
100
  const request = this.requestQueue.get(requestId);
210
101
  if (request) {
211
102
  request.callPromise?.reject(error);
212
- request.settled.resolve();
213
103
  }
104
+ this.releaseTask(requestId);
214
105
  }
215
106
 
216
107
  // 删除请求
217
108
  public releaseTask(requestId: number) {
218
- const task = this.requestQueue.get(requestId);
219
- const operationId = task?.method.payload?.operationId;
220
- if (
221
- typeof operationId === 'string' &&
222
- this.operationRequestIds.get(operationId) === requestId
223
- ) {
224
- this.operationRequestIds.delete(operationId);
225
- }
226
- task?.settled.resolve();
227
- task?.released.resolve();
228
109
  this.requestQueue.delete(requestId);
229
110
  }
230
111
 
package/src/core/index.ts CHANGED
@@ -196,25 +196,34 @@ export const callAPI = async (context: CoreContext, message: CoreMessage) => {
196
196
  // );
197
197
  // }
198
198
 
199
+ const { requestQueue, methodSynchronize } = context;
200
+ const error = await methodSynchronize(() => {
201
+ for (const requestId of requestQueue.getRequestTasksId()) {
202
+ const task = requestQueue.getTask(requestId);
203
+ Log.debug(
204
+ 'pre request task: ',
205
+ `task?.id: ${task?.id},
206
+ task?.method.connectId: ${task?.method.connectId},
207
+ task?.method.deviceId: ${task?.method.deviceId},
208
+ task?.method.name: ${task?.method.name}`
209
+ );
210
+ // if (task) {
211
+ // return Promise.reject(ERRORS.TypedError(HardwareErrorCode.DeviceBusy));
212
+ // }
213
+ }
214
+ return null;
215
+ });
216
+
217
+ if (error) {
218
+ return createResponseMessage(method.responseID, false, { error });
219
+ }
220
+
199
221
  // only the pre-warm signal (PreInitialize) forks here; normal methods fall
200
222
  // through to onCallDevice below, so the pre-warm dedup/guards never touch them
201
223
  if (method.isPreWarmSignal) {
202
224
  return handlePreWarmSignal(context, message, method);
203
225
  }
204
226
 
205
- const { requestQueue, methodSynchronize } = context;
206
- const admission = await methodSynchronize(
207
- () => requestQueue.admitTask(method),
208
- method.connectId ?? method.deviceId ?? 'unknown-device'
209
- );
210
- if (admission.status === 'busy') {
211
- const error = ERRORS.TypedError(HardwareErrorCode.DeviceBusy);
212
- DevicePool.emitter.removeListener(DEVICE.CONNECT, onDeviceConnectHandler);
213
- completeMethodRequestContext(method, error);
214
- method.dispose();
215
- return createResponseMessage(method.responseID, false, { error });
216
- }
217
-
218
227
  return onCallDevice(context, message, method);
219
228
  };
220
229
 
@@ -334,7 +343,7 @@ const onCallDevice = async (
334
343
 
335
344
  await waitForPendingPromise(getPrePendingCallPromise, setPrePendingCallPromise);
336
345
 
337
- const task = requestQueue.getTask(method.responseID) ?? requestQueue.createTask(method);
346
+ const task = requestQueue.createTask(method);
338
347
 
339
348
  // Pre-warm holds the device as a per-connectId callback task so a concurrent
340
349
  // real call waits (before ensureConnected) instead of racing its Initialize.
@@ -378,10 +387,6 @@ const onCallDevice = async (
378
387
  if (method.payload?.onlyConnectBleDevice) {
379
388
  preWarmCallbackTask?.resolve();
380
389
  Log.debug('Call API - only connect ble device: ', device?.mainId);
381
- DevicePool.emitter.removeListener(DEVICE.CONNECT, onDeviceConnectHandler);
382
- requestQueue.releaseTask(method.responseID);
383
- completeMethodRequestContext(method);
384
- method.dispose();
385
390
  return createResponseMessage(method.responseID, true, null);
386
391
  }
387
392
 
@@ -661,9 +666,8 @@ const onCallDevice = async (
661
666
  skipInitialize: canSkipInitialize(method, device),
662
667
  ...parseInitOptions(method),
663
668
  };
664
- const deviceRunPromise = device.run(inner, runOptions);
665
- task.callPromise = createDeferred<any>();
666
- deviceRunPromise.catch(error => task.callPromise?.reject(error));
669
+ const deviceRun = () => device.run(inner, runOptions);
670
+ task.callPromise = createDeferred<any>(deviceRun);
667
671
 
668
672
  try {
669
673
  return await task.callPromise.promise;
@@ -671,8 +675,6 @@ const onCallDevice = async (
671
675
  Log.debug('Device Run Error: ', e);
672
676
  completeMethodRequestContext(method, e);
673
677
  return createResponseMessage(method.responseID, false, { error: e });
674
- } finally {
675
- await deviceRunPromise.catch(() => undefined);
676
678
  }
677
679
  } catch (error) {
678
680
  messageResponse = createResponseMessage(method.responseID, false, { error });
@@ -1389,10 +1391,6 @@ export default class Core extends EventEmitter {
1389
1391
  Log.debug(`[Core] Created SDK instance: ${this.sdkInstanceId}`);
1390
1392
  }
1391
1393
 
1392
- cancelOperation(operationId: string) {
1393
- this.requestQueue.abortOperation(operationId);
1394
- }
1395
-
1396
1394
  private getCoreContext() {
1397
1395
  return {
1398
1396
  sdkInstanceId: this.sdkInstanceId,
@@ -1468,10 +1466,6 @@ export default class Core extends EventEmitter {
1468
1466
  cancel(this.getCoreContext(), message.payload.connectId);
1469
1467
  break;
1470
1468
  }
1471
- case IFRAME.CANCEL_OPERATION: {
1472
- this.cancelOperation(message.payload.operationId);
1473
- break;
1474
- }
1475
1469
  case IFRAME.CALLBACK: {
1476
1470
  Log.log('callback message: ', message);
1477
1471
  postMessage(message);
@@ -955,7 +955,7 @@ export class Device extends EventEmitter {
955
955
  'DeviceSettings',
956
956
  {}
957
957
  );
958
- this.updateState(mapDeviceSettingsToState(message), 'apply-settings');
958
+ this.updateState(mapDeviceSettingsToState(message), 'settings-read');
959
959
  }
960
960
  }
961
961
 
@@ -1,14 +1,5 @@
1
1
  import type { Features } from '../types';
2
2
 
3
- export type DeviceFeaturesUpdateSource =
4
- | 'device-info'
5
- | 'device-status'
6
- | 'device-settings-get'
7
- | 'device-settings-set'
8
- | 'apply-settings'
9
- | 'unlock'
10
- | 'cache';
11
-
12
3
  /**
13
4
  * Merge a field-level device-state patch.
14
5
  *
@@ -1,7 +1,11 @@
1
1
  import { EDeviceType, EFirmwareType } from '@onekeyfe/hd-shared';
2
2
 
3
3
  import { buildProtocolV1FeaturesPayload } from '../deviceProfile/buildDeviceFeatures';
4
- import { mapLanguageToProtocolV2 } from '../utils/deviceSettings';
4
+ import {
5
+ mapLanguageFromProtocolV2,
6
+ mapLanguageToProtocolV2,
7
+ normalizeSafetyCheckLevel,
8
+ } from '../utils/deviceSettings';
5
9
 
6
10
  import type {
7
11
  ApplySettings,
@@ -289,9 +293,10 @@ export const mapApplySettingsToState = (settings: ApplySettings): DeviceStatePat
289
293
  autoShutdownDelayMs: settings.auto_shutdown_delay_ms,
290
294
  displayRotation: settings.display_rotation,
291
295
  passphraseAlwaysOnDevice: settings.passphrase_always_on_device,
292
- safetyChecks: settings.safety_checks,
296
+ safetyChecks: normalizeSafetyCheckLevel(settings.safety_checks),
293
297
  experimentalFeatures: settings.experimental_features,
294
298
  hapticFeedback: settings.haptic_feedback,
299
+ bleEnabled: settings.use_ble,
295
300
  });
296
301
  return {
297
302
  ...(Object.keys(identity).length ? { identity } : {}),
@@ -301,14 +306,11 @@ export const mapApplySettingsToState = (settings: ApplySettings): DeviceStatePat
301
306
  };
302
307
 
303
308
  export const mapDeviceSettingsToState = (settings: DeviceSettings): DeviceStatePatch => {
304
- const settingsWithExperimental = settings as DeviceSettings & {
305
- experimental_features?: boolean;
306
- };
307
309
  const identity = definedEntries({ label: settings.label });
308
310
  const status = definedEntries({ passphraseProtection: settings.passphrase_enable });
309
311
  const stateSettings = definedEntries({
310
312
  bleEnabled: settings.bt_enable,
311
- language: settings.language,
313
+ language: mapLanguageFromProtocolV2(settings.language),
312
314
  wallpaperPath: settings.wallpaper_path,
313
315
  brightness: settings.brightness,
314
316
  autoLockDelayMs: settings.autolock_delay_ms,
@@ -319,7 +321,6 @@ export const mapDeviceSettingsToState = (settings: DeviceSettings): DeviceStateP
319
321
  deviceNameDisplayEnabled: settings.device_name_display_enabled,
320
322
  airgapMode: settings.airgap_mode,
321
323
  fidoEnabled: settings.fido_enabled,
322
- experimentalFeatures: settingsWithExperimental.experimental_features,
323
324
  usbLockEnabled: settings.usb_lock_enable,
324
325
  randomKeypad: settings.random_keypad,
325
326
  });
@@ -10,6 +10,7 @@ import {
10
10
  resolveDeviceSerialNo,
11
11
  resolveDeviceType,
12
12
  } from '../utils/deviceFeaturesCompat';
13
+ import { normalizeSafetyCheckLevel } from '../utils/deviceSettings';
13
14
 
14
15
  import type {
15
16
  DeviceFirmwareImageInfo,
@@ -121,7 +122,7 @@ export const buildProtocolV1FeaturesPayload = (
121
122
  passphraseAlwaysOnDevice: features.passphrase_always_on_device ?? null,
122
123
  attachToPinEnabled: features.attach_to_pin_user ?? previous?.attachToPinEnabled ?? null,
123
124
  unlockedAttachPin: features.unlocked_attach_pin ?? previous?.unlockedAttachPin ?? undefined,
124
- safetyChecks: features.safety_checks ?? null,
125
+ safetyChecks: normalizeSafetyCheckLevel(features.safety_checks) ?? null,
125
126
  autoLockDelayMs: features.auto_lock_delay_ms ?? null,
126
127
  autoShutdownDelayMs: features.auto_shutdown_delay_ms ?? null,
127
128
  displayRotation: features.display_rotation ?? null,
@@ -53,12 +53,6 @@ export interface IFrameCancelMessage {
53
53
  payload: { connectId?: string };
54
54
  }
55
55
 
56
- export interface IFrameCancelOperationMessage {
57
- event: typeof IFRAME.CANCEL_OPERATION;
58
- type: typeof IFRAME.CANCEL_OPERATION;
59
- payload: { operationId: string };
60
- }
61
-
62
56
  export interface IFrameSwitchTransportMessage {
63
57
  event: typeof IFRAME.SWITCH_TRANSPORT;
64
58
  type: typeof IFRAME.SWITCH_TRANSPORT;
@@ -5,7 +5,6 @@ import type {
5
5
  IFrameCallMessage,
6
6
  IFrameCallbackMessage,
7
7
  IFrameCancelMessage,
8
- IFrameCancelOperationMessage,
9
8
  IFrameSwitchTransportMessage,
10
9
  } from './call';
11
10
  import type { DeviceEventMessage } from './device';
@@ -24,7 +23,6 @@ export type CoreMessage = {
24
23
  | IFrameEventMessage
25
24
  | IFrameCallMessage
26
25
  | IFrameCancelMessage
27
- | IFrameCancelOperationMessage
28
26
  | IFrameSwitchTransportMessage
29
27
  | IFrameCallbackMessage
30
28
  | UiResponseMessage
@@ -8,7 +8,6 @@ export const IFRAME = {
8
8
  INIT_BRIDGE: 'iframe-init-bridge',
9
9
  CALL: 'iframe-call',
10
10
  CANCEL: 'iframe-cancel',
11
- CANCEL_OPERATION: 'iframe-cancel-operation',
12
11
  SWITCH_TRANSPORT: 'iframe-switch-transport',
13
12
  CALLBACK: 'iframe-callback',
14
13
  } as const;
package/src/index.ts CHANGED
@@ -27,7 +27,6 @@ const HardwareSdk = ({
27
27
  eventEmitter,
28
28
  uiResponse,
29
29
  cancel,
30
- cancelOperation,
31
30
  updateSettings,
32
31
  switchTransport,
33
32
  }: InjectApi): CoreApi =>
@@ -38,7 +37,6 @@ const HardwareSdk = ({
38
37
  eventEmitter,
39
38
  uiResponse,
40
39
  cancel,
41
- cancelOperation,
42
40
  updateSettings,
43
41
  switchTransport,
44
42
  });
@@ -51,7 +49,6 @@ const HardwareSDKLowLevel = ({
51
49
  addHardwareGlobalEventListener,
52
50
  uiResponse,
53
51
  cancel,
54
- cancelOperation,
55
52
  updateSettings,
56
53
  switchTransport,
57
54
  }: LowLevelInjectApi): LowLevelCoreApi =>
@@ -63,7 +60,6 @@ const HardwareSDKLowLevel = ({
63
60
  addHardwareGlobalEventListener,
64
61
  uiResponse,
65
62
  cancel,
66
- cancelOperation,
67
63
  updateSettings,
68
64
  switchTransport,
69
65
  });
package/src/inject.ts CHANGED
@@ -36,14 +36,12 @@ export interface InjectApi {
36
36
  dispose: CoreApi['dispose'];
37
37
  uiResponse: CoreApi['uiResponse'];
38
38
  cancel: CoreApi['cancel'];
39
- cancelOperation: CoreApi['cancelOperation'];
40
39
  switchTransport: CoreApi['switchTransport'];
41
40
  }
42
41
 
43
42
  export const inject = ({
44
43
  call,
45
44
  cancel,
46
- cancelOperation,
47
45
  dispose,
48
46
  eventEmitter,
49
47
  init,
@@ -75,7 +73,6 @@ export const inject = ({
75
73
  uiResponse,
76
74
 
77
75
  cancel,
78
- cancelOperation,
79
76
 
80
77
  updateSettings,
81
78
 
@@ -99,7 +96,6 @@ export const createCoreApi = (
99
96
  | 'dispose'
100
97
  | 'uiResponse'
101
98
  | 'cancel'
102
- | 'cancelOperation'
103
99
  | 'updateSettings'
104
100
  | 'switchTransport'
105
101
  > => ({
@@ -166,8 +162,6 @@ export const createCoreApi = (
166
162
  call({ ...params, connectId, method: 'deviceUploadWallpaper' }),
167
163
  deviceInfoGet: (connectId, params) => call({ ...params, connectId, method: 'deviceInfoGet' }),
168
164
  deviceStatusGet: (connectId, params) => call({ ...params, connectId, method: 'deviceStatusGet' }),
169
- deviceSettingsGet: (connectId, params) =>
170
- call({ ...params, connectId, method: 'deviceSettingsGet' }),
171
165
  protocolInfoRequest: (connectId, params) =>
172
166
  call({ ...params, connectId, method: 'protocolInfoRequest' }),
173
167
  ping: (connectId, params) => call({ ...params, connectId, method: 'ping' }),
@@ -179,10 +173,6 @@ export const createCoreApi = (
179
173
  call({ ...params, connectId, method: 'deviceFactoryInfoSet' }),
180
174
  deviceFactoryInfoGet: (connectId, params) =>
181
175
  call({ ...params, connectId, method: 'deviceFactoryInfoGet' }),
182
- deviceSettingsSet: (connectId, params) =>
183
- call({ ...params, connectId, method: 'deviceSettingsSet' }),
184
- deviceSettingsPageShow: (connectId, params) =>
185
- call({ ...params, connectId, method: 'deviceSettingsPageShow' }),
186
176
  filesystemPermissionFix: (connectId, params) =>
187
177
  call({ ...params, connectId, method: 'filesystemPermissionFix' }),
188
178
  filesystemFormat: connectId => call({ connectId, method: 'filesystemFormat' }),
@@ -13,7 +13,6 @@ export interface LowLevelInjectApi {
13
13
  dispose: CoreApi['dispose'];
14
14
  uiResponse: CoreApi['uiResponse'];
15
15
  cancel: CoreApi['cancel'];
16
- cancelOperation: CoreApi['cancelOperation'];
17
16
  updateSettings: CoreApi['updateSettings'];
18
17
  switchTransport: CoreApi['switchTransport'];
19
18
  addHardwareGlobalEventListener: (listener: IAddHardwareGlobalEventListener) => void;
@@ -26,7 +25,6 @@ export type LowLevelCoreApi = Omit<CoreApi, 'on' | 'off'> & {
26
25
  export const lowLevelInject = ({
27
26
  call,
28
27
  cancel,
29
- cancelOperation,
30
28
  dispose,
31
29
  eventEmitter,
32
30
  init,
@@ -50,7 +48,6 @@ export const lowLevelInject = ({
50
48
  uiResponse,
51
49
 
52
50
  cancel,
53
- cancelOperation,
54
51
 
55
52
  updateSettings,
56
53
 
@@ -52,8 +52,6 @@ export const topLevelInject = () => {
52
52
 
53
53
  cancel: (connectId?: string) => lowLevelApi?.cancel(connectId),
54
54
 
55
- cancelOperation: (operationId: string) => lowLevelApi?.cancelOperation(operationId),
56
-
57
55
  updateSettings: settings => lowLevelApi?.updateSettings(settings) ?? Promise.resolve(false),
58
56
 
59
57
  switchTransport: (env: ConnectSettings['env']) =>