@onekeyfe/hd-core 1.1.27-alpha.31 → 1.1.27-alpha.33

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 (59) hide show
  1. package/__tests__/evmSignTransaction.test.ts +1 -1
  2. package/__tests__/evmSignTypedData.test.ts +1 -1
  3. package/__tests__/protocol-v2.test.ts +319 -9
  4. package/dist/api/DirList.d.ts.map +1 -1
  5. package/dist/api/DirMake.d.ts.map +1 -1
  6. package/dist/api/DirRemove.d.ts.map +1 -1
  7. package/dist/api/FileDelete.d.ts.map +1 -1
  8. package/dist/api/FileRead.d.ts.map +1 -1
  9. package/dist/api/FileWrite.d.ts.map +1 -1
  10. package/dist/api/GetPassphraseState.d.ts.map +1 -1
  11. package/dist/api/PathInfo.d.ts.map +1 -1
  12. package/dist/api/helpers/filesystemValidation.d.ts +7 -0
  13. package/dist/api/helpers/filesystemValidation.d.ts.map +1 -0
  14. package/dist/api/protocol-v2/DeviceFirmwareUpdate.d.ts.map +1 -1
  15. package/dist/api/protocol-v2/helpers.d.ts.map +1 -1
  16. package/dist/core/index.d.ts.map +1 -1
  17. package/dist/data-manager/DataManager.d.ts +2 -2
  18. package/dist/data-manager/DataManager.d.ts.map +1 -1
  19. package/dist/data-manager/TransportManager.d.ts.map +1 -1
  20. package/dist/index.d.ts +8 -5
  21. package/dist/index.js +185 -83
  22. package/dist/protocols/protocol-v2/features.d.ts +1 -1
  23. package/dist/protocols/protocol-v2/features.d.ts.map +1 -1
  24. package/dist/types/api/getPassphraseState.d.ts +4 -1
  25. package/dist/types/api/getPassphraseState.d.ts.map +1 -1
  26. package/dist/types/api/index.d.ts +1 -1
  27. package/dist/types/api/index.d.ts.map +1 -1
  28. package/dist/utils/deviceFeaturesUtils.d.ts +2 -0
  29. package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
  30. package/dist/utils/patch.d.ts +1 -1
  31. package/package.json +4 -4
  32. package/src/api/DirList.ts +6 -2
  33. package/src/api/DirMake.ts +2 -1
  34. package/src/api/DirRemove.ts +2 -1
  35. package/src/api/FileDelete.ts +2 -1
  36. package/src/api/FileRead.ts +12 -5
  37. package/src/api/FileWrite.ts +19 -7
  38. package/src/api/GetPassphraseState.ts +5 -1
  39. package/src/api/PathInfo.ts +2 -1
  40. package/src/api/evm/EVMGetAddress.ts +1 -1
  41. package/src/api/evm/EVMGetPublicKey.ts +1 -1
  42. package/src/api/evm/EVMSignMessage.ts +1 -1
  43. package/src/api/evm/EVMSignTransaction.ts +1 -1
  44. package/src/api/evm/EVMSignTypedData.ts +4 -4
  45. package/src/api/evm/EVMVerifyMessage.ts +1 -1
  46. package/src/api/helpers/filesystemValidation.ts +51 -0
  47. package/src/api/protocol-v2/DeviceFirmwareUpdate.ts +2 -1
  48. package/src/api/protocol-v2/helpers.ts +34 -11
  49. package/src/core/index.ts +12 -4
  50. package/src/data-manager/DataManager.ts +7 -7
  51. package/src/data-manager/MessagesConfig.ts +6 -6
  52. package/src/data-manager/TransportManager.ts +4 -4
  53. package/src/device/Device.ts +2 -2
  54. package/src/protocols/protocol-v2/features.ts +37 -40
  55. package/src/protocols/protocol-v2/firmware.ts +1 -1
  56. package/src/types/api/getPassphraseState.ts +5 -1
  57. package/src/types/api/index.ts +1 -1
  58. package/src/utils/deviceFeaturesUtils.ts +26 -10
  59. /package/src/data/messages/{messages-pro2.json → messages-protocol-v2.json} +0 -0
@@ -16,7 +16,11 @@ export default class GetPassphraseState extends BaseMethod {
16
16
  return Promise.reject(ERRORS.TypedError(HardwareErrorCode.DeviceInitializeFailed));
17
17
 
18
18
  const { passphraseState, newSession, unlockedAttachPin } =
19
- await getPassphraseStateWithRefreshDeviceInfo(this.device);
19
+ await getPassphraseStateWithRefreshDeviceInfo(this.device, {
20
+ expectPassphraseState: this.payload.passphraseState,
21
+ onlyMainPin: this.payload.useEmptyPassphrase,
22
+ allowCreateAttachPin: this.payload.allowCreateAttachPin,
23
+ });
20
24
 
21
25
  const { features } = this.device;
22
26
  const isPro2 = getDeviceType(features) === EDeviceType.Pro2;
@@ -1,4 +1,5 @@
1
1
  import { BaseMethod } from './BaseMethod';
2
+ import { validateNonEmptyString } from './helpers/filesystemValidation';
2
3
 
3
4
  export type PathInfoParams = {
4
5
  path: string;
@@ -8,7 +9,7 @@ export default class PathInfo extends BaseMethod<PathInfoParams> {
8
9
  init() {
9
10
  this.skipForceUpdateCheck = true;
10
11
  this.useDevicePassphraseState = false;
11
- this.params = { path: this.payload.path };
12
+ this.params = { path: validateNonEmptyString(this.payload.path, 'path') };
12
13
  }
13
14
 
14
15
  async run() {
@@ -44,7 +44,7 @@ export default class EvmGetAddress extends BaseMethod<EthereumGetAddressOneKey[]
44
44
  }
45
45
 
46
46
  async getEvmAddress(param: EthereumGetAddressOneKey) {
47
- if (TransportManager.getProtocolV1MessageSchema() === 'protocolV1Legacy') {
47
+ if (TransportManager.getProtocolV1MessageSchema() === 'v1LegacySchema') {
48
48
  return getAddressLegacyV1({
49
49
  typedCall: this.device.commands.typedCall.bind(this.device.commands),
50
50
  param,
@@ -57,7 +57,7 @@ export default class EVMGetPublicKey extends BaseMethod<EthereumGetPublicKeyOneK
57
57
  }
58
58
 
59
59
  getEvmPublicKey(param: EthereumGetPublicKey) {
60
- if (TransportManager.getProtocolV1MessageSchema() === 'protocolV1Legacy') {
60
+ if (TransportManager.getProtocolV1MessageSchema() === 'v1LegacySchema') {
61
61
  return getPublicKeyLegacyV1({
62
62
  typedCall: this.device.commands.typedCall.bind(this.device.commands),
63
63
  param,
@@ -34,7 +34,7 @@ export default class EVMSignMessage extends BaseMethod<EthereumSignMessageOneKey
34
34
  }
35
35
 
36
36
  async run() {
37
- if (TransportManager.getProtocolV1MessageSchema() === 'protocolV1Legacy') {
37
+ if (TransportManager.getProtocolV1MessageSchema() === 'v1LegacySchema') {
38
38
  return signMessageLegacyV1({
39
39
  typedCall: this.device.commands.typedCall.bind(this.device.commands),
40
40
  params: this.params,
@@ -120,7 +120,7 @@ export default class EVMSignTransaction extends BaseMethod {
120
120
 
121
121
  if (formattedTx == null) throw ERRORS.TypedError('Runtime', 'formattedTx is not set');
122
122
 
123
- if (TransportManager.getProtocolV1MessageSchema() === 'protocolV1Legacy') {
123
+ if (TransportManager.getProtocolV1MessageSchema() === 'v1LegacySchema') {
124
124
  return signTransactionLegacyV1({
125
125
  typedCall: this.device.commands.typedCall.bind(this.device.commands),
126
126
  addressN,
@@ -261,7 +261,7 @@ export default class EVMSignTypedData extends BaseMethod<EVMSignTypedDataParams>
261
261
  let supportTrezor = false;
262
262
  let response: MessageResponse<MessageKey>;
263
263
  switch (TransportManager.getProtocolV1MessageSchema()) {
264
- case 'protocolV1Legacy':
264
+ case 'v1LegacySchema':
265
265
  supportTrezor = true;
266
266
  response = await signTypedDataLegacyV1({
267
267
  typedCall: this.device.commands.typedCall.bind(this.device.commands),
@@ -272,7 +272,7 @@ export default class EVMSignTypedData extends BaseMethod<EVMSignTypedDataParams>
272
272
  });
273
273
  break;
274
274
 
275
- case 'protocolV1Current':
275
+ case 'v1CurrentSchema':
276
276
  default:
277
277
  supportTrezor = false;
278
278
  response = await signTypedData({
@@ -309,7 +309,7 @@ export default class EVMSignTypedData extends BaseMethod<EVMSignTypedDataParams>
309
309
  if (!domainHash) throw ERRORS.TypedError('Runtime', 'domainHash is required');
310
310
 
311
311
  switch (TransportManager.getProtocolV1MessageSchema()) {
312
- case 'protocolV1Legacy':
312
+ case 'v1LegacySchema':
313
313
  return signTypedHashLegacyV1({
314
314
  typedCall,
315
315
  addressN,
@@ -319,7 +319,7 @@ export default class EVMSignTypedData extends BaseMethod<EVMSignTypedDataParams>
319
319
  device: this.device,
320
320
  });
321
321
 
322
- case 'protocolV1Current':
322
+ case 'v1CurrentSchema':
323
323
  default:
324
324
  return signTypedHash({
325
325
  typedCall,
@@ -31,7 +31,7 @@ export default class EVMSignMessage extends BaseMethod<EthereumVerifyMessageOneK
31
31
  }
32
32
 
33
33
  async run() {
34
- if (TransportManager.getProtocolV1MessageSchema() === 'protocolV1Legacy') {
34
+ if (TransportManager.getProtocolV1MessageSchema() === 'v1LegacySchema') {
35
35
  return verifyMessageLegacyV1({
36
36
  typedCall: this.device.commands.typedCall.bind(this.device.commands),
37
37
  params: this.params,
@@ -0,0 +1,51 @@
1
+ import { ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
2
+
3
+ export const invalidParameter = (message: string) =>
4
+ ERRORS.TypedError(HardwareErrorCode.CallMethodInvalidParameter, message);
5
+
6
+ export function validateNonEmptyString(value: unknown, name: string): string {
7
+ if (typeof value !== 'string' || value.trim().length === 0) {
8
+ throw invalidParameter(`Parameter [${name}] is required and must be a non-empty string.`);
9
+ }
10
+ return value;
11
+ }
12
+
13
+ export function validateNonNegativeInteger(
14
+ value: unknown,
15
+ name: string,
16
+ defaultValue?: number
17
+ ): number {
18
+ if (value === undefined || value === null) {
19
+ if (defaultValue !== undefined) return defaultValue;
20
+ throw invalidParameter(`Missing required parameter: ${name}`);
21
+ }
22
+
23
+ const numeric = typeof value === 'string' && value.trim() !== '' ? Number(value) : value;
24
+ if (typeof numeric !== 'number' || !Number.isSafeInteger(numeric) || numeric < 0) {
25
+ throw invalidParameter(`Parameter [${name}] must be a non-negative integer.`);
26
+ }
27
+ return numeric;
28
+ }
29
+
30
+ export function validateOptionalNonNegativeInteger(
31
+ value: unknown,
32
+ name: string
33
+ ): number | undefined {
34
+ if (value === undefined || value === null) return undefined;
35
+ return validateNonNegativeInteger(value, name);
36
+ }
37
+
38
+ export function validateOptionalPercentage(value: unknown, name: string): number | undefined {
39
+ const numeric = validateOptionalNonNegativeInteger(value, name);
40
+ if (numeric === undefined) return undefined;
41
+ if (numeric > 100) {
42
+ throw invalidParameter(`Parameter [${name}] must be between 0 and 100.`);
43
+ }
44
+ return numeric;
45
+ }
46
+
47
+ export function validateRequiredData(value: unknown, name: string): void {
48
+ if (value === undefined || value === null) {
49
+ throw invalidParameter(`Missing required parameter: ${name}`);
50
+ }
51
+ }
@@ -20,11 +20,12 @@ export default class DeviceFirmwareUpdate extends BaseMethod<DeviceFirmwareUpdat
20
20
  }
21
21
 
22
22
  async run() {
23
+ const targets = normalizeFirmwareTargets(this.params);
23
24
  const res = await this.device.commands.typedCall(
24
25
  'DeviceFirmwareUpdate',
25
26
  PROTOCOL_V2_FIRMWARE_UPDATE_RESPONSE_TYPES,
26
27
  {
27
- targets: normalizeFirmwareTargets(this.params),
28
+ targets,
28
29
  },
29
30
  PROTOCOL_V2_FIRMWARE_UPDATE_OPTIONS
30
31
  );
@@ -1,5 +1,7 @@
1
1
  import { DeviceRebootType } from '@onekeyfe/hd-transport';
2
2
 
3
+ import { invalidParameter, validateNonEmptyString } from '../helpers/filesystemValidation';
4
+
3
5
  import type {
4
6
  DeviceFirmwareTarget,
5
7
  DeviceFirmwareTargetType,
@@ -69,8 +71,10 @@ export const PROTOCOL_V2_FIRMWARE_UPDATE_OPTIONS: TransportCallOptions = {
69
71
  intermediateTypes: ['DeviceFirmwareInstallProgress'],
70
72
  };
71
73
 
72
- export const PROTOCOL_V2_FIRMWARE_UPDATE_RESPONSE_TYPES: ('Success' | 'DeviceFirmwareUpdateStatus')[] =
73
- ['Success', 'DeviceFirmwareUpdateStatus'];
74
+ export const PROTOCOL_V2_FIRMWARE_UPDATE_RESPONSE_TYPES: (
75
+ | 'Success'
76
+ | 'DeviceFirmwareUpdateStatus'
77
+ )[] = ['Success', 'DeviceFirmwareUpdateStatus'];
74
78
 
75
79
  export function normalizeRebootType(value: RebootTypeInput | undefined): DeviceRebootType {
76
80
  if (typeof value === 'number') return value;
@@ -83,15 +87,24 @@ export function normalizeRebootType(value: RebootTypeInput | undefined): DeviceR
83
87
  }
84
88
 
85
89
  function normalizeTargetId(
86
- value: DeviceFirmwareTargetType | string | number | undefined
90
+ value: DeviceFirmwareTargetType | string | number | undefined,
91
+ name: string
87
92
  ): DeviceFirmwareTargetType {
88
- if (typeof value === 'number') return value;
93
+ if (value === undefined || value === null) {
94
+ throw invalidParameter(`Missing required parameter: ${name}`);
95
+ }
96
+ if (typeof value === 'number') {
97
+ if (Number.isSafeInteger(value) && value > 0) return value;
98
+ throw invalidParameter(`Parameter [${name}] must be a valid firmware target id.`);
99
+ }
89
100
  const numeric = Number(value);
90
- if (Number.isFinite(numeric)) return numeric;
91
- return 0;
101
+ if (Number.isSafeInteger(numeric) && numeric > 0) return numeric;
102
+ throw invalidParameter(`Parameter [${name}] must be a valid firmware target id.`);
92
103
  }
93
104
 
94
- export function normalizeFirmwareTargets(params: DeviceFirmwareUpdateParams): DeviceFirmwareTarget[] {
105
+ export function normalizeFirmwareTargets(
106
+ params: DeviceFirmwareUpdateParams
107
+ ): DeviceFirmwareTarget[] {
95
108
  const targets =
96
109
  params.targets ??
97
110
  (params.path
@@ -103,10 +116,20 @@ export function normalizeFirmwareTargets(params: DeviceFirmwareUpdateParams): De
103
116
  ]
104
117
  : []);
105
118
 
106
- return targets.map(target => ({
107
- target_id: normalizeTargetId('target_id' in target ? target.target_id : target.targetId),
108
- path: target.path,
109
- }));
119
+ if (!Array.isArray(targets) || targets.length === 0) {
120
+ throw invalidParameter('Parameter [targets] must contain at least one firmware target.');
121
+ }
122
+
123
+ return targets.map((target, index) => {
124
+ if (!target || typeof target !== 'object') {
125
+ throw invalidParameter(`Parameter [targets.${index}] must be an object.`);
126
+ }
127
+ const targetId = target.target_id ?? target.targetId;
128
+ return {
129
+ target_id: normalizeTargetId(targetId, `targets.${index}.target_id`),
130
+ path: validateNonEmptyString(target.path, `targets.${index}.path`),
131
+ };
132
+ });
110
133
  }
111
134
 
112
135
  export function buildTargets(params: DeviceGetDeviceInfoParams): DeviceInfoTargets | undefined {
package/src/core/index.ts CHANGED
@@ -479,7 +479,7 @@ const onCallDevice = async (
479
479
  // Check to see if it is safe to use Passphrase
480
480
  checkPassphraseEnableState(method, device.features);
481
481
 
482
- if (device.hasUsePassphrase() && method.useDevicePassphraseState) {
482
+ if (shouldCheckPassphraseState(method, device)) {
483
483
  // check version
484
484
  const support = supportNewPassphrase(device.features);
485
485
  if (!support.support) {
@@ -994,8 +994,6 @@ export const cancel = (context: CoreContext, connectId?: string) => {
994
994
  const checkPassphraseEnableState = (method: BaseMethod, features?: Features) => {
995
995
  if (!method.useDevicePassphraseState) return;
996
996
 
997
- const isPro2 = getDeviceType(features) === EDeviceType.Pro2;
998
-
999
997
  if (features?.passphrase_protection === true) {
1000
998
  const hasNoPassphraseState =
1001
999
  method.payload.passphraseState == null || method.payload.passphraseState === '';
@@ -1008,12 +1006,22 @@ const checkPassphraseEnableState = (method: BaseMethod, features?: Features) =>
1008
1006
  }
1009
1007
  }
1010
1008
 
1011
- if (features?.passphrase_protection === false && method.payload.passphraseState && !isPro2) {
1009
+ if (features?.passphrase_protection === false && method.payload.passphraseState) {
1012
1010
  DevicePool.clearDeviceCache(method.payload.connectId);
1013
1011
  throw ERRORS.TypedError(HardwareErrorCode.DeviceNotOpenedPassphrase);
1014
1012
  }
1015
1013
  };
1016
1014
 
1015
+ const shouldCheckPassphraseState = (method: BaseMethod, device: Device) => {
1016
+ if (!method.useDevicePassphraseState) return false;
1017
+
1018
+ const isPro2 = getDeviceType(device.features) === EDeviceType.Pro2;
1019
+ const pro2ExplicitWalletSelection =
1020
+ isPro2 && (!!method.payload?.passphraseState || !!method.payload?.useEmptyPassphrase);
1021
+
1022
+ return device.hasUsePassphrase() || pro2ExplicitWalletSelection;
1023
+ };
1024
+
1017
1025
  const cleanup = () => {
1018
1026
  _uiPromises = [];
1019
1027
  Log.debug('Cleanup...');
@@ -4,7 +4,7 @@ import { EDeviceType, EFirmwareType } from '@onekeyfe/hd-shared';
4
4
 
5
5
  import MessagesJSON from '../data/messages/messages.json';
6
6
  import MessagesLegacyV1JSON from '../data/messages/messages_legacy_v1.json';
7
- import MessagesPro2JSON from '../data/messages/messages-pro2.json';
7
+ import MessagesProtocolV2JSON from '../data/messages/messages-protocol-v2.json';
8
8
  import {
9
9
  LoggerNames,
10
10
  getDeviceBLEFirmwareVersion,
@@ -41,8 +41,8 @@ export const FIRMWARE_FIELDS = [
41
41
 
42
42
  export type IFirmwareField = (typeof FIRMWARE_FIELDS)[number];
43
43
 
44
- export type ProtocolV1MessageSchema = 'protocolV1Current' | 'protocolV1Legacy';
45
- export type ProtobufMessageSchema = ProtocolV1MessageSchema | 'protocolV2';
44
+ export type ProtocolV1MessageSchema = 'v1CurrentSchema' | 'v1LegacySchema';
45
+ export type ProtobufMessageSchema = ProtocolV1MessageSchema | 'v2Schema';
46
46
 
47
47
  const FIRMWARE_FIELD_TYPE_MAP: Readonly<Record<IFirmwareField, EFirmwareType>> = {
48
48
  firmware: EFirmwareType.Universal,
@@ -98,9 +98,9 @@ export default class DataManager {
98
98
  static settings: ConnectSettings;
99
99
 
100
100
  static messages: { [schema in ProtobufMessageSchema]: JSON } = {
101
- protocolV1Current: MessagesJSON as unknown as JSON,
102
- protocolV1Legacy: MessagesLegacyV1JSON as unknown as JSON,
103
- protocolV2: MessagesPro2JSON as unknown as JSON,
101
+ v1CurrentSchema: MessagesJSON as unknown as JSON,
102
+ v1LegacySchema: MessagesLegacyV1JSON as unknown as JSON,
103
+ v2Schema: MessagesProtocolV2JSON as unknown as JSON,
104
104
  };
105
105
 
106
106
  static lastCheckTimestamp = 0;
@@ -477,7 +477,7 @@ export default class DataManager {
477
477
  }
478
478
  }
479
479
 
480
- static getProtobufMessages(schema: ProtobufMessageSchema = 'protocolV1Current'): JSON {
480
+ static getProtobufMessages(schema: ProtobufMessageSchema = 'v1CurrentSchema'): JSON {
481
481
  return this.messages[schema];
482
482
  }
483
483
 
@@ -12,17 +12,17 @@ export const PROTOBUF_MESSAGE_CONFIG: DeviceVersionConfig = {
12
12
  model_mini: [
13
13
  // Classic1s starts from 3.5.0, so use the current Protocol V1 schema by default.
14
14
  // Only use the legacy Protocol V1 schema for specific old versions (< 3.3.0).
15
- { minVersion: '3.3.0', protocolV1MessageSchema: 'protocolV1Current' },
16
- { minVersion: '0.0.1', protocolV1MessageSchema: 'protocolV1Legacy' },
15
+ { minVersion: '3.3.0', protocolV1MessageSchema: 'v1CurrentSchema' },
16
+ { minVersion: '0.0.1', protocolV1MessageSchema: 'v1LegacySchema' },
17
17
  // Fallback to current Protocol V1 schema for unknown versions (0.0.0).
18
- { minVersion: '0.0.0', protocolV1MessageSchema: 'protocolV1Current' },
18
+ { minVersion: '0.0.0', protocolV1MessageSchema: 'v1CurrentSchema' },
19
19
  ],
20
20
  model_touch: [
21
21
  // Use the current Protocol V1 schema by default for Touch/Pro.
22
22
  // Only use the legacy Protocol V1 schema for specific old versions (< 4.5.0).
23
- { minVersion: '4.5.0', protocolV1MessageSchema: 'protocolV1Current' },
24
- { minVersion: '0.0.1', protocolV1MessageSchema: 'protocolV1Legacy' },
23
+ { minVersion: '4.5.0', protocolV1MessageSchema: 'v1CurrentSchema' },
24
+ { minVersion: '0.0.1', protocolV1MessageSchema: 'v1LegacySchema' },
25
25
  // Fallback to current Protocol V1 schema for unknown versions (0.0.0).
26
- { minVersion: '0.0.0', protocolV1MessageSchema: 'protocolV1Current' },
26
+ { minVersion: '0.0.0', protocolV1MessageSchema: 'v1CurrentSchema' },
27
27
  ],
28
28
  };
@@ -33,7 +33,7 @@ export default class TransportManager {
33
33
 
34
34
  static reactNativeInit = false;
35
35
 
36
- static protocolV1MessageSchema: ProtocolV1MessageSchema = 'protocolV1Current';
36
+ static protocolV1MessageSchema: ProtocolV1MessageSchema = 'v1CurrentSchema';
37
37
 
38
38
  static plugin: LowlevelTransportSharedPlugin | null = null;
39
39
 
@@ -41,7 +41,7 @@ export default class TransportManager {
41
41
  Log.debug('transport manager load');
42
42
  this.defaultMessages = DataManager.getProtobufMessages();
43
43
  this.currentMessages = this.defaultMessages;
44
- this.protocolV1MessageSchema = 'protocolV1Current';
44
+ this.protocolV1MessageSchema = 'v1CurrentSchema';
45
45
  }
46
46
 
47
47
  static async configure() {
@@ -76,7 +76,7 @@ export default class TransportManager {
76
76
  Log.debug('Configuring transports');
77
77
  await this.transport.configure(JSON.stringify(this.defaultMessages));
78
78
  this.currentMessages = this.defaultMessages;
79
- this.protocolV1MessageSchema = 'protocolV1Current';
79
+ this.protocolV1MessageSchema = 'v1CurrentSchema';
80
80
  await this.configureProtocolV2Messages();
81
81
  Log.debug('Configuring transports done');
82
82
  } catch (error) {
@@ -148,7 +148,7 @@ export default class TransportManager {
148
148
  }
149
149
 
150
150
  private static async configureProtocolV2Messages() {
151
- const protocolV2Messages = DataManager.getProtobufMessages('protocolV2');
151
+ const protocolV2Messages = DataManager.getProtobufMessages('v2Schema');
152
152
  const { configureProtocolV2 } = this.transport;
153
153
  if (protocolV2Messages && typeof configureProtocolV2 === 'function') {
154
154
  await configureProtocolV2.call(this.transport, JSON.stringify(protocolV2Messages));
@@ -543,8 +543,8 @@ export class Device extends EventEmitter {
543
543
  /**
544
544
  * Device initialization over Protocol V2.
545
545
  *
546
- * Protocol V2 不走传统 Initialize/GetFeatures,当前仅通过 Ping 验证链路,
547
- * 然后使用 descriptor 生成临时 Features 视图。
546
+ * Protocol V2 不走传统 Initialize/GetFeatures,当前通过 Ping 验证链路,
547
+ * 再用 DeviceGetDeviceInfo 归一成 legacy-style Features 视图。
548
548
  */
549
549
  private async _initializeProtocolV2() {
550
550
  Log.debug('Initialize device via Protocol V2 feature adapter');
@@ -53,24 +53,24 @@ type ProtocolV2DeviceInfo = {
53
53
  };
54
54
  };
55
55
 
56
- // const PROTOCOL_V2_DEVICE_INFO_REQUEST = {
57
- // targets: {
58
- // hw: true,
59
- // fw: true,
60
- // bt: true,
61
- // se1: true,
62
- // se2: true,
63
- // se3: true,
64
- // se4: true,
65
- // status: true,
66
- // },
67
- // types: {
68
- // version: true,
69
- // build_id: true,
70
- // hash: true,
71
- // specific: true,
72
- // },
73
- // };
56
+ const PROTOCOL_V2_DEVICE_INFO_REQUEST = {
57
+ targets: {
58
+ hw: true,
59
+ fw: true,
60
+ bt: true,
61
+ se1: true,
62
+ se2: true,
63
+ se3: true,
64
+ se4: true,
65
+ status: true,
66
+ },
67
+ types: {
68
+ version: true,
69
+ build_id: true,
70
+ hash: true,
71
+ specific: true,
72
+ },
73
+ };
74
74
 
75
75
  function parseVersion(version?: string | null): [number, number, number] {
76
76
  if (!version) return [0, 0, 0];
@@ -228,7 +228,7 @@ export function normalizeProtocolV2Features(
228
228
  export async function getProtocolV2Features({
229
229
  commands,
230
230
  descriptor,
231
- // onDeviceInfoError,
231
+ onDeviceInfoError,
232
232
  timeoutMs,
233
233
  }: {
234
234
  commands: DeviceCommands;
@@ -243,25 +243,22 @@ export async function getProtocolV2Features({
243
243
  await commands.typedCall('Ping', 'Success', { message: 'init' });
244
244
  }
245
245
 
246
- // DeviceGetDeviceInfo 暂时关闭,避免初始化阶段依赖固件侧 DeviceInfo 支持。
247
- // try {
248
- // const { message } = callOptions
249
- // ? await commands.typedCall(
250
- // 'DeviceGetDeviceInfo',
251
- // 'DeviceInfo',
252
- // PROTOCOL_V2_DEVICE_INFO_REQUEST,
253
- // callOptions
254
- // )
255
- // : await commands.typedCall(
256
- // 'DeviceGetDeviceInfo',
257
- // 'DeviceInfo',
258
- // PROTOCOL_V2_DEVICE_INFO_REQUEST
259
- // );
260
- // return normalizeProtocolV2Features(descriptor, message as unknown as ProtocolV2DeviceInfo);
261
- // } catch (error) {
262
- // onDeviceInfoError?.(error);
263
- // return normalizeProtocolV2Features(descriptor);
264
- // }
265
-
266
- return normalizeProtocolV2Features(descriptor);
246
+ try {
247
+ const { message } = callOptions
248
+ ? await commands.typedCall(
249
+ 'DeviceGetDeviceInfo',
250
+ 'DeviceInfo',
251
+ PROTOCOL_V2_DEVICE_INFO_REQUEST,
252
+ callOptions
253
+ )
254
+ : await commands.typedCall(
255
+ 'DeviceGetDeviceInfo',
256
+ 'DeviceInfo',
257
+ PROTOCOL_V2_DEVICE_INFO_REQUEST
258
+ );
259
+ return normalizeProtocolV2Features(descriptor, message as unknown as ProtocolV2DeviceInfo);
260
+ } catch (error) {
261
+ onDeviceInfoError?.(error);
262
+ return normalizeProtocolV2Features(descriptor);
263
+ }
267
264
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Protocol V2 DeviceFirmwareTargetType enum (from messages-pro2.json).
2
+ * Protocol V2 DeviceFirmwareTargetType enum (from messages-protocol-v2.json).
3
3
  */
4
4
  export const ProtocolV2FirmwareTargetType = {
5
5
  TARGET_INVALID: 0,
@@ -9,7 +9,11 @@ export type GetPassphraseStatePayload =
9
9
  passphrase_protection?: boolean | null;
10
10
  };
11
11
 
12
+ export type GetPassphraseStateParams = CommonParams & {
13
+ allowCreateAttachPin?: boolean;
14
+ };
15
+
12
16
  export declare function getPassphraseState(
13
17
  connectId?: string,
14
- params?: CommonParams
18
+ params?: GetPassphraseStateParams
15
19
  ): Response<GetPassphraseStatePayload>;
@@ -162,7 +162,7 @@ import type { neoSignTransaction } from './neoSignTransaction';
162
162
  import type { ConnectSettings } from '../settings';
163
163
 
164
164
  export * from './export';
165
- export type { GetPassphraseStatePayload } from './getPassphraseState';
165
+ export type { GetPassphraseStateParams, GetPassphraseStatePayload } from './getPassphraseState';
166
166
 
167
167
  export type CoreApi = {
168
168
  /**
@@ -1,7 +1,10 @@
1
1
  import semver from 'semver';
2
2
  import { isNaN } from 'lodash';
3
3
  import { EDeviceType, type EFirmwareType, ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
4
- import { Enum_Capability } from '@onekeyfe/hd-transport';
4
+ import {
5
+ Enum_Capability,
6
+ type GetPassphraseState as GetPassphraseStateMessage,
7
+ } from '@onekeyfe/hd-transport';
5
8
 
6
9
  import { toHardened } from '../api/helpers/pathUtils';
7
10
  import { DeviceModelToTypes, DeviceTypeToModels } from '../types';
@@ -23,8 +26,8 @@ export const getSupportProtocolV1MessageSchema = (
23
26
  ): { messages: JSON; protocolV1MessageSchema: ProtocolV1MessageSchema } => {
24
27
  if (!features)
25
28
  return {
26
- messages: DataManager.messages.protocolV1Current,
27
- protocolV1MessageSchema: 'protocolV1Current',
29
+ messages: DataManager.messages.v1CurrentSchema,
30
+ protocolV1MessageSchema: 'v1CurrentSchema',
28
31
  };
29
32
 
30
33
  const currentDeviceVersion = getDeviceFirmwareVersion(features).join('.');
@@ -50,8 +53,8 @@ export const getSupportProtocolV1MessageSchema = (
50
53
  }
51
54
 
52
55
  return {
53
- messages: DataManager.messages.protocolV1Current,
54
- protocolV1MessageSchema: 'protocolV1Current',
56
+ messages: DataManager.messages.v1CurrentSchema,
57
+ protocolV1MessageSchema: 'v1CurrentSchema',
55
58
  };
56
59
  };
57
60
 
@@ -89,6 +92,7 @@ export const getPassphraseStateWithRefreshDeviceInfo = async (
89
92
  options?: {
90
93
  expectPassphraseState?: string;
91
94
  onlyMainPin?: boolean;
95
+ allowCreateAttachPin?: boolean;
92
96
  }
93
97
  ) => {
94
98
  const { features, commands } = device;
@@ -119,8 +123,10 @@ export const getPassphraseStateWithRefreshDeviceInfo = async (
119
123
  await device.getFeatures();
120
124
  }
121
125
 
122
- if (isPro2 && device.features && (passphraseState || newSession)) {
123
- device.features.passphrase_protection = true;
126
+ if (isPro2 && device.features) {
127
+ if (passphraseState) {
128
+ device.features.passphrase_protection = true;
129
+ }
124
130
  if (newSession) {
125
131
  device.features.session_id = newSession;
126
132
  }
@@ -146,6 +152,7 @@ export const getPassphraseState = async (
146
152
  options?: {
147
153
  expectPassphraseState?: string;
148
154
  onlyMainPin?: boolean;
155
+ allowCreateAttachPin?: boolean;
149
156
  }
150
157
  ): Promise<{
151
158
  passphraseState: string | undefined;
@@ -169,9 +176,18 @@ export const getPassphraseState = async (
169
176
  (deviceType === EDeviceType.Pro && semver.gte(firmwareVersion.join('.'), '4.15.0'));
170
177
 
171
178
  if (supportGetPassphraseState) {
172
- const { message, type } = await commands.typedCall('GetPassphraseState', 'PassphraseState', {
173
- passphrase_state: options?.onlyMainPin ? undefined : options?.expectPassphraseState,
174
- });
179
+ const payload: GetPassphraseStateMessage = options?.onlyMainPin
180
+ ? { _only_main_pin: true }
181
+ : { passphrase_state: options?.expectPassphraseState };
182
+ if (options?.allowCreateAttachPin) {
183
+ payload.allow_create_attach_pin = true;
184
+ }
185
+
186
+ const { message, type } = await commands.typedCall(
187
+ 'GetPassphraseState',
188
+ 'PassphraseState',
189
+ payload
190
+ );
175
191
 
176
192
  // @ts-expect-error
177
193
  if (type === 'CallMethodError') {