@onekeyfe/hd-core 1.0.36-alpha.1 → 1.0.37-alpha.3

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 (62) hide show
  1. package/dist/api/GetPassphraseState.d.ts +1 -1
  2. package/dist/api/allnetwork/AllNetworkGetAddress.d.ts +3 -1
  3. package/dist/api/allnetwork/AllNetworkGetAddress.d.ts.map +1 -1
  4. package/dist/api/device/DeviceUnlock.d.ts +7 -0
  5. package/dist/api/device/DeviceUnlock.d.ts.map +1 -0
  6. package/dist/api/index.d.ts +1 -0
  7. package/dist/api/index.d.ts.map +1 -1
  8. package/dist/api/stellar/StellarSignTransaction.d.ts.map +1 -1
  9. package/dist/core/index.d.ts.map +1 -1
  10. package/dist/data-manager/DataManager.d.ts.map +1 -1
  11. package/dist/data-manager/TransportManager.d.ts.map +1 -1
  12. package/dist/device/Device.d.ts +9 -4
  13. package/dist/device/Device.d.ts.map +1 -1
  14. package/dist/device/DeviceCommands.d.ts +7 -5
  15. package/dist/device/DeviceCommands.d.ts.map +1 -1
  16. package/dist/events/device.d.ts +3 -0
  17. package/dist/events/device.d.ts.map +1 -1
  18. package/dist/events/ui-request.d.ts +2 -1
  19. package/dist/events/ui-request.d.ts.map +1 -1
  20. package/dist/events/ui-response.d.ts +1 -0
  21. package/dist/events/ui-response.d.ts.map +1 -1
  22. package/dist/index.d.ts +28 -11
  23. package/dist/index.js +213 -68
  24. package/dist/inject.d.ts.map +1 -1
  25. package/dist/types/api/deviceUnlock.d.ts +4 -0
  26. package/dist/types/api/deviceUnlock.d.ts.map +1 -0
  27. package/dist/types/api/index.d.ts +2 -0
  28. package/dist/types/api/index.d.ts.map +1 -1
  29. package/dist/types/params.d.ts +1 -0
  30. package/dist/types/params.d.ts.map +1 -1
  31. package/dist/types/settings.d.ts +1 -1
  32. package/dist/types/settings.d.ts.map +1 -1
  33. package/dist/utils/deviceFeaturesUtils.d.ts +16 -2
  34. package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
  35. package/dist/utils/logger.d.ts +2 -0
  36. package/dist/utils/logger.d.ts.map +1 -1
  37. package/dist/utils/patch.d.ts +1 -1
  38. package/dist/utils/patch.d.ts.map +1 -1
  39. package/package.json +4 -4
  40. package/src/api/FirmwareUpdate.ts +1 -1
  41. package/src/api/GetPassphraseState.ts +4 -4
  42. package/src/api/allnetwork/AllNetworkGetAddress.ts +18 -20
  43. package/src/api/device/DeviceUnlock.ts +26 -0
  44. package/src/api/firmware/FirmwareUpdateBaseMethod.ts +2 -2
  45. package/src/api/index.ts +1 -0
  46. package/src/api/stellar/StellarSignTransaction.ts +0 -3
  47. package/src/core/index.ts +17 -8
  48. package/src/data/messages/messages.json +49 -2
  49. package/src/data-manager/DataManager.ts +1 -1
  50. package/src/data-manager/TransportManager.ts +3 -0
  51. package/src/device/Device.ts +92 -20
  52. package/src/device/DeviceCommands.ts +15 -5
  53. package/src/events/device.ts +4 -0
  54. package/src/events/ui-request.ts +2 -1
  55. package/src/events/ui-response.ts +1 -0
  56. package/src/inject.ts +2 -0
  57. package/src/types/api/deviceUnlock.ts +4 -0
  58. package/src/types/api/index.ts +2 -0
  59. package/src/types/params.ts +5 -0
  60. package/src/types/settings.ts +10 -1
  61. package/src/utils/deviceFeaturesUtils.ts +72 -8
  62. package/src/utils/logger.ts +2 -0
@@ -0,0 +1,26 @@
1
+ import { LockDevice } from '@onekeyfe/hd-transport';
2
+ import { ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
3
+ import { BaseMethod } from '../BaseMethod';
4
+ import { toHardened } from '../helpers/pathUtils';
5
+
6
+ export default class DeviceUnlock extends BaseMethod<LockDevice> {
7
+ init() {
8
+ this.useDevicePassphraseState = false;
9
+ }
10
+
11
+ async run() {
12
+ const { type } = await this.device.commands.typedCall('GetAddress', 'Address', {
13
+ address_n: [toHardened(44), toHardened(1), toHardened(0), 0, 0],
14
+ coin_name: 'Testnet',
15
+ script_type: 'SPENDADDRESS',
16
+ show_display: false,
17
+ });
18
+
19
+ // @ts-expect-error
20
+ if (type === 'CallMethodError') {
21
+ throw ERRORS.TypedError(HardwareErrorCode.RuntimeError, 'Get the passphrase state error');
22
+ }
23
+ const res = await this.device.commands.typedCall('GetFeatures', 'Features');
24
+ return Promise.resolve(res.message);
25
+ }
26
+ }
@@ -306,9 +306,9 @@ export class FirmwareUpdateBaseMethod<Params> extends BaseMethod<Params> {
306
306
  let progress: number;
307
307
  if (totalSize !== undefined && processedSize !== undefined) {
308
308
  currentFileProcessed = processedSize + chunkEnd;
309
- progress = Math.min(Math.floor((currentFileProcessed / totalSize) * 100), 100);
309
+ progress = Math.min(Math.ceil((currentFileProcessed / totalSize) * 100), 99);
310
310
  } else {
311
- progress = Math.min(Math.round(((i + 1) / totalChunks) * 100), 100);
311
+ progress = Math.min(Math.ceil(((i + 1) / totalChunks) * 100), 99);
312
312
  }
313
313
 
314
314
  const writeRes = await this.emmcFileWriteWithRetry(
package/src/api/index.ts CHANGED
@@ -27,6 +27,7 @@ export { default as deviceWipe } from './device/DeviceWipe';
27
27
  export { default as deviceFullyUploadResource } from './device/DeviceFullyUploadResource';
28
28
  export { default as deviceUpdateBootloader } from './device/DeviceUpdateBootloader';
29
29
  export { default as deviceLock } from './device/DeviceLock';
30
+ export { default as deviceUnlock } from './device/DeviceUnlock';
30
31
  export { default as deviceCancel } from './device/DeviceCancel';
31
32
 
32
33
  export { default as setU2FCounter } from './u2f/SetU2FCounter';
@@ -194,9 +194,6 @@ export default class StellarSignTransaction extends BaseMethod<HardwareStellarSi
194
194
  this.operations.push(transformed);
195
195
  }
196
196
  });
197
-
198
- console.log('StellarSignTransactionParams', this.params);
199
- console.log('StellarSignTransactionOperations', this.operations);
200
197
  }
201
198
 
202
199
  processTxRequest = async (operations: any, index: number): Promise<StellarSignedTx> => {
package/src/core/index.ts CHANGED
@@ -342,7 +342,9 @@ const onCallDevice = async (
342
342
 
343
343
  // Check Device passphrase State
344
344
  const passphraseStateSafety = await device.checkPassphraseStateSafety(
345
- method.payload?.passphraseState
345
+ method.payload?.passphraseState,
346
+ method.payload?.useEmptyPassphrase,
347
+ method.payload?.skipPassphraseCheck
346
348
  );
347
349
 
348
350
  // Double check, handles the special case of Touch/Pro
@@ -354,6 +356,9 @@ const onCallDevice = async (
354
356
  ERRORS.TypedError(HardwareErrorCode.DeviceCheckPassphraseStateError)
355
357
  );
356
358
  }
359
+
360
+ // close pin popup window
361
+ postMessage(createUiMessage(UI_REQUEST.CLOSE_UI_WINDOW));
357
362
  }
358
363
 
359
364
  // Automatic check safety_check level for Kovan, Ropsten, Rinkeby, Goerli test networks.
@@ -774,7 +779,7 @@ const checkPassphraseEnableState = (method: BaseMethod, features?: Features) =>
774
779
  if (
775
780
  features?.passphrase_protection === true &&
776
781
  (method.payload.passphraseState == null || method.payload.passphraseState === '') &&
777
- !method.payload.useEmptyPassphrase
782
+ (!method.payload.useEmptyPassphrase || !method.payload.skipPassphraseCheck)
778
783
  ) {
779
784
  DevicePool.clearDeviceCache(method.payload.connectId);
780
785
  throw ERRORS.TypedError(HardwareErrorCode.DeviceOpenedPassphrase);
@@ -836,12 +841,12 @@ const onDevicePinHandler = async (...[device, type, callback]: DeviceEvents['pin
836
841
  const onDeviceButtonHandler = (...[device, request]: [...DeviceEvents['button']]) => {
837
842
  postMessage(createDeviceMessage(DEVICE.BUTTON, { ...request, device: device.toMessageObject() }));
838
843
 
839
- if (request.code === 'ButtonRequest_PinEntry') {
840
- Log.log('request Confirm Input PIN');
844
+ if (request.code === 'ButtonRequest_PinEntry' || request.code === 'ButtonRequest_AttachPin') {
845
+ Log.log('request Confirm Input PIN or Attach PIN');
841
846
  postMessage(
842
847
  createUiMessage(UI_REQUEST.REQUEST_PIN, {
843
848
  device: device.toMessageObject() as KnownDevice,
844
- type: 'ButtonRequest_PinEntry',
849
+ type: request.code,
845
850
  })
846
851
  );
847
852
  } else {
@@ -854,27 +859,31 @@ const onDeviceFeaturesHandler = (...[_, features]: [...DeviceEvents['features']]
854
859
  postMessage(createDeviceMessage(DEVICE.FEATURES, { ...features }));
855
860
  };
856
861
 
857
- const onDevicePassphraseHandler = async (...[device, callback]: DeviceEvents['passphrase']) => {
862
+ const onDevicePassphraseHandler = async (
863
+ ...[device, requestPayload, callback]: DeviceEvents['passphrase']
864
+ ) => {
858
865
  Log.debug('onDevicePassphraseHandler');
859
866
  const uiPromise = createUiPromise(UI_RESPONSE.RECEIVE_PASSPHRASE, device);
860
867
  postMessage(
861
868
  createUiMessage(UI_REQUEST.REQUEST_PASSPHRASE, {
862
869
  device: device.toMessageObject() as KnownDevice,
863
870
  passphraseState: device.passphraseState,
871
+ existsAttachPinUser: requestPayload.existsAttachPinUser,
864
872
  })
865
873
  );
866
874
  // wait for passphrase
867
875
  const uiResp = await uiPromise.promise;
868
- const { value, passphraseOnDevice, save } = uiResp.payload;
876
+ const { value, passphraseOnDevice, save, attachPinOnDevice } = uiResp.payload;
869
877
  // send as PassphrasePromptResponse
870
878
  callback({
871
879
  passphrase: value.normalize('NFKD'),
872
880
  passphraseOnDevice,
881
+ attachPinOnDevice,
873
882
  cache: save,
874
883
  });
875
884
  };
876
885
 
877
- const onEmptyPassphraseHandler = (...[_, callback]: DeviceEvents['passphrase']) => {
886
+ const onEmptyPassphraseHandler = (...[_, , callback]: DeviceEvents['passphrase']) => {
878
887
  Log.debug('onEmptyPassphraseHandler');
879
888
  // send as PassphrasePromptResponse
880
889
  callback({ passphrase: '' });
@@ -3021,7 +3021,8 @@
3021
3021
  "ButtonRequest_Success": 17,
3022
3022
  "ButtonRequest_Warning": 18,
3023
3023
  "ButtonRequest_PassphraseEntry": 19,
3024
- "ButtonRequest_PinEntry": 20
3024
+ "ButtonRequest_PinEntry": 20,
3025
+ "ButtonRequest_AttachPin": 8000
3025
3026
  }
3026
3027
  }
3027
3028
  }
@@ -3071,6 +3072,10 @@
3071
3072
  "options": {
3072
3073
  "deprecated": true
3073
3074
  }
3075
+ },
3076
+ "exists_attach_pin_user": {
3077
+ "type": "bool",
3078
+ "id": 8000
3074
3079
  }
3075
3080
  }
3076
3081
  },
@@ -3090,6 +3095,10 @@
3090
3095
  "on_device": {
3091
3096
  "type": "bool",
3092
3097
  "id": 3
3098
+ },
3099
+ "on_device_attach_pin": {
3100
+ "type": "bool",
3101
+ "id": 8000
3093
3102
  }
3094
3103
  }
3095
3104
  },
@@ -6051,6 +6060,10 @@
6051
6060
  "derive_cardano": {
6052
6061
  "type": "bool",
6053
6062
  "id": 3
6063
+ },
6064
+ "passphrase_state": {
6065
+ "type": "string",
6066
+ "id": 8000
6054
6067
  }
6055
6068
  }
6056
6069
  },
@@ -6429,6 +6442,14 @@
6429
6442
  "onekey_se04_state": {
6430
6443
  "type": "OneKeySEState",
6431
6444
  "id": 624
6445
+ },
6446
+ "attach_to_pin_user": {
6447
+ "type": "bool",
6448
+ "id": 625
6449
+ },
6450
+ "unlocked_attach_pin": {
6451
+ "type": "bool",
6452
+ "id": 626
6432
6453
  }
6433
6454
  },
6434
6455
  "nested": {
@@ -7533,6 +7554,30 @@
7533
7554
  }
7534
7555
  }
7535
7556
  },
7557
+ "GetPassphraseState": {
7558
+ "fields": {
7559
+ "passphrase_state": {
7560
+ "type": "string",
7561
+ "id": 1
7562
+ }
7563
+ }
7564
+ },
7565
+ "PassphraseState": {
7566
+ "fields": {
7567
+ "passphrase_state": {
7568
+ "type": "string",
7569
+ "id": 1
7570
+ },
7571
+ "session_id": {
7572
+ "type": "bytes",
7573
+ "id": 2
7574
+ },
7575
+ "unlocked_attach_pin": {
7576
+ "type": "bool",
7577
+ "id": 3
7578
+ }
7579
+ }
7580
+ },
7536
7581
  "MoneroTransactionSourceEntry": {
7537
7582
  "fields": {
7538
7583
  "outputs": {
@@ -12144,7 +12189,9 @@
12144
12189
  "MessageType_ListResDir": 10023,
12145
12190
  "MessageType_FileInfoList": 10024,
12146
12191
  "MessageType_OnekeyGetFeatures": 10025,
12147
- "MessageType_OnekeyFeatures": 10026
12192
+ "MessageType_OnekeyFeatures": 10026,
12193
+ "MessageType_GetPassphraseState": 10028,
12194
+ "MessageType_PassphraseState": 10029
12148
12195
  }
12149
12196
  },
12150
12197
  "google": {
@@ -349,7 +349,7 @@ export default class DataManager {
349
349
  }
350
350
 
351
351
  static isBleConnect = (env: ConnectSettings['env']) =>
352
- env === 'react-native' || env === 'lowlevel';
352
+ env === 'react-native' || env === 'lowlevel' || env === 'desktop-web-ble';
353
353
 
354
354
  static isWebUsbConnect = (env: ConnectSettings['env']) => env === 'webusb';
355
355
  }
@@ -11,6 +11,7 @@ const Log = getLogger(LoggerNames.Transport);
11
11
  const BleLogger = getLogger(LoggerNames.HdBleTransport);
12
12
  const HttpLogger = getLogger(LoggerNames.HdTransportHttp);
13
13
  const LowLevelLogger = getLogger(LoggerNames.HdTransportLowLevel);
14
+ const WebBleLogger = getLogger(LoggerNames.HdWebBleTransport);
14
15
 
15
16
  /**
16
17
  * transport 在同一个环境中只会存在一个
@@ -56,6 +57,8 @@ export default class TransportManager {
56
57
  );
57
58
  }
58
59
  await this.transport.init(LowLevelLogger, DevicePool.emitter, this.plugin);
60
+ } else if (env === 'desktop-web-ble') {
61
+ await this.transport.init(WebBleLogger);
59
62
  } else {
60
63
  await this.transport.init(HttpLogger);
61
64
  }
@@ -33,7 +33,13 @@ import {
33
33
  type Features,
34
34
  type UnavailableCapabilities,
35
35
  } from '../types';
36
- import { DEVICE, DeviceButtonRequestPayload, DeviceFeaturesPayload, UI_REQUEST } from '../events';
36
+ import {
37
+ DEVICE,
38
+ DeviceButtonRequestPayload,
39
+ DeviceFeaturesPayload,
40
+ PassphraseRequestPayload,
41
+ UI_REQUEST,
42
+ } from '../events';
37
43
  import { PROTO } from '../constants';
38
44
  import { DataManager } from '../data-manager';
39
45
  import TransportManager from '../data-manager/TransportManager';
@@ -61,7 +67,11 @@ export interface DeviceEvents {
61
67
  [DEVICE.PASSPHRASE_ON_DEVICE]: [Device, ((response: any) => void)?];
62
68
  [DEVICE.BUTTON]: [Device, DeviceButtonRequestPayload];
63
69
  [DEVICE.FEATURES]: [Device, DeviceFeaturesPayload];
64
- [DEVICE.PASSPHRASE]: [Device, (response: PassphrasePromptResponse, error?: Error) => void];
70
+ [DEVICE.PASSPHRASE]: [
71
+ Device,
72
+ PassphraseRequestPayload,
73
+ (response: PassphrasePromptResponse, error?: Error) => void
74
+ ];
65
75
  [DEVICE.SELECT_DEVICE_IN_BOOTLOADER_FOR_WEB_DEVICE]: [
66
76
  Device,
67
77
  (err: any, deviceId: string) => void
@@ -288,13 +298,13 @@ export class Device extends EventEmitter {
288
298
  }
289
299
 
290
300
  getInternalState(_deviceId?: string) {
301
+ Log.debug('getInternalState session cache: ', deviceSessionCache);
291
302
  Log.debug(
292
303
  'getInternalState session param: ',
293
304
  `device_id: ${_deviceId}`,
294
305
  `features.device_id: ${this.features?.device_id}`,
295
306
  `passphraseState: ${this.passphraseState}`
296
307
  );
297
- Log.debug('getInternalState session cache: ', deviceSessionCache);
298
308
 
299
309
  const deviceId = _deviceId || this.features?.device_id;
300
310
  if (!deviceId) return undefined;
@@ -304,23 +314,39 @@ export class Device extends EventEmitter {
304
314
  return deviceSessionCache[usePassKey];
305
315
  }
306
316
 
307
- tryFixInternalState(state: string, deviceId: string, sessionId: string | null = null) {
317
+ // attach to pin to fix internal state
318
+ updateInternalState(
319
+ enablePassphrase: boolean,
320
+ passphraseState: string | undefined,
321
+ deviceId: string,
322
+ sessionId: string | null = null,
323
+ featuresSessionId: string | null = null
324
+ ) {
308
325
  Log.debug(
309
- 'tryFixInternalState session param: ',
326
+ 'updateInternalState session param: ',
310
327
  `device_id: ${deviceId}`,
311
- `passphraseState: ${state}`,
312
- `sessionId: ${sessionId}`
328
+ `enablePassphrase: ${enablePassphrase}`,
329
+ `passphraseState: ${passphraseState}`,
330
+ `sessionId: ${sessionId}`,
331
+ `featuresSessionId: ${featuresSessionId}`
313
332
  );
314
333
 
315
- const key = `${deviceId}`;
316
- const session = deviceSessionCache[key];
317
- if (session) {
318
- deviceSessionCache[this.generateStateKey(deviceId, state)] = session;
319
- delete deviceSessionCache[key];
320
- } else if (sessionId) {
321
- deviceSessionCache[this.generateStateKey(deviceId, state)] = sessionId;
334
+ if (enablePassphrase) {
335
+ // update the sessionId
336
+ if (sessionId) {
337
+ deviceSessionCache[this.generateStateKey(deviceId, passphraseState)] = sessionId;
338
+ } else if (featuresSessionId) {
339
+ deviceSessionCache[this.generateStateKey(deviceId, passphraseState)] = featuresSessionId;
340
+ }
322
341
  }
323
- Log.debug('tryFixInternalState session cache: ', deviceSessionCache);
342
+
343
+ // delete the old sessionId
344
+ const oldKey = `${deviceId}`;
345
+ if (deviceSessionCache[oldKey]) {
346
+ delete deviceSessionCache[oldKey];
347
+ }
348
+
349
+ Log.debug('updateInternalState session cache: ', deviceSessionCache);
324
350
  }
325
351
 
326
352
  private setInternalState(state: string, initSession?: boolean) {
@@ -361,7 +387,7 @@ export class Device extends EventEmitter {
361
387
  }
362
388
 
363
389
  async initialize(options?: InitOptions) {
364
- Log.debug('initialize param:', options);
390
+ // Log.debug('initialize param:', options);
365
391
 
366
392
  this.passphraseState = options?.passphraseState;
367
393
 
@@ -378,8 +404,14 @@ export class Device extends EventEmitter {
378
404
  if (options?.deriveCardano) {
379
405
  payload.derive_cardano = true;
380
406
  }
407
+ payload.passphrase_state = options?.passphraseState;
381
408
 
382
- Log.debug('initialize payload:', payload);
409
+ Log.debug('Initialize device begin:', {
410
+ deviceId: options?.deviceId,
411
+ passphraseState: options?.passphraseState,
412
+ initSession: options?.initSession,
413
+ InitializePayload: payload,
414
+ });
383
415
 
384
416
  try {
385
417
  // @ts-expect-error
@@ -393,6 +425,7 @@ export class Device extends EventEmitter {
393
425
  }),
394
426
  ]);
395
427
 
428
+ Log.debug('Initialize device end: ', message);
396
429
  this._updateFeatures(message, options?.initSession);
397
430
  await TransportManager.reconfigure(this.features);
398
431
  } catch (error) {
@@ -693,12 +726,51 @@ export class Device extends EventEmitter {
693
726
  return false;
694
727
  }
695
728
 
696
- async checkPassphraseStateSafety(passphraseState?: string) {
729
+ async lockDevice() {
730
+ const res = await this.commands.typedCall('LockDevice', 'Success', {});
731
+ return res.message;
732
+ }
733
+
734
+ async checkPassphraseStateSafety(
735
+ passphraseState?: string,
736
+ useEmptyPassphraseState?: boolean,
737
+ skipPassphraseCheck?: boolean
738
+ ) {
697
739
  if (!this.features) return false;
698
- const newState = await getPassphraseStateWithRefreshDeviceInfo(this);
740
+ const { passphraseState: newPassphraseState, unlockedAttachPin } =
741
+ await getPassphraseStateWithRefreshDeviceInfo(this, {
742
+ expectPassphraseState: passphraseState,
743
+ onlyMainPin: useEmptyPassphraseState,
744
+ });
745
+
746
+ if (skipPassphraseCheck) {
747
+ return true;
748
+ }
749
+
750
+ // Main wallet and unlock Attach Pin, throw safe error
751
+ const mainWalletUseAttachPin = unlockedAttachPin && useEmptyPassphraseState;
752
+ const useErrorAttachPin =
753
+ unlockedAttachPin && passphraseState && passphraseState !== newPassphraseState;
754
+
755
+ Log.debug('Check passphrase state safety: ', {
756
+ passphraseState,
757
+ newPassphraseState,
758
+ unlockedAttachPin,
759
+ useEmptyPassphraseState,
760
+ });
761
+
762
+ if (mainWalletUseAttachPin || useErrorAttachPin) {
763
+ try {
764
+ await this.lockDevice();
765
+ } catch (error) {
766
+ // ignore error
767
+ }
768
+ this.clearInternalState();
769
+ return Promise.reject(ERRORS.TypedError(HardwareErrorCode.DeviceCheckUnlockTypeError));
770
+ }
699
771
 
700
772
  // When exists passphraseState, check passphraseState
701
- if (passphraseState && passphraseState !== newState) {
773
+ if (passphraseState && passphraseState !== newPassphraseState) {
702
774
  this.clearInternalState();
703
775
  return false;
704
776
  }
@@ -4,12 +4,13 @@ import TransportManager from '../data-manager/TransportManager';
4
4
  import DataManager from '../data-manager/DataManager';
5
5
  import { patchFeatures, getLogger, LoggerNames, getDeviceType } from '../utils';
6
6
  import type { Device } from './Device';
7
- import { DEVICE } from '../events';
7
+ import { DEVICE, type PassphraseRequestPayload } from '../events';
8
8
  import { DeviceModelToTypes } from '../types';
9
9
 
10
10
  export type PassphrasePromptResponse = {
11
11
  passphrase?: string;
12
12
  passphraseOnDevice?: boolean;
13
+ attachPinOnDevice?: boolean;
13
14
  cache?: boolean;
14
15
  };
15
16
 
@@ -217,7 +218,6 @@ export class DeviceCommands {
217
218
  this.callPromise = promise;
218
219
  const res = await promise;
219
220
  Log.debug('[DeviceCommands] [call] Received', res.type);
220
- console.log('[DeviceCommands] [call] Received', res.type);
221
221
  return res;
222
222
  } catch (error) {
223
223
  Log.debug('[DeviceCommands] [call] Received error', error);
@@ -438,8 +438,17 @@ export class DeviceCommands {
438
438
  }
439
439
 
440
440
  if (res.type === 'PassphraseRequest') {
441
- return this._promptPassphrase().then(response => {
442
- const { passphrase, passphraseOnDevice } = response;
441
+ const existsAttachPinUser = res.message.exists_attach_pin_user;
442
+ return this._promptPassphrase({
443
+ existsAttachPinUser,
444
+ }).then(response => {
445
+ const { passphrase, passphraseOnDevice, attachPinOnDevice } = response;
446
+
447
+ // Attach PIN on device
448
+ if (attachPinOnDevice && existsAttachPinUser) {
449
+ return this._commonCall('PassphraseAck', { on_device_attach_pin: true });
450
+ }
451
+
443
452
  return !passphraseOnDevice
444
453
  ? this._commonCall('PassphraseAck', { passphrase })
445
454
  : this._commonCall('PassphraseAck', { on_device: true });
@@ -501,7 +510,7 @@ export class DeviceCommands {
501
510
  });
502
511
  }
503
512
 
504
- _promptPassphrase() {
513
+ _promptPassphrase(options: PassphraseRequestPayload) {
505
514
  return new Promise<PassphrasePromptResponse>((resolve, reject) => {
506
515
  const cancelAndReject = (_error?: Error) =>
507
516
  cancelDeviceInPrompt(this.device, false)
@@ -527,6 +536,7 @@ export class DeviceCommands {
527
536
  this.device.emit(
528
537
  DEVICE.PASSPHRASE,
529
538
  this.device,
539
+ options,
530
540
  (response: PassphrasePromptResponse, error?: Error) => {
531
541
  this.device.clearCancelableAction();
532
542
  if (error) {
@@ -44,6 +44,10 @@ export interface DeviceButtonRequestPayload extends Omit<PROTO.ButtonRequest, 'c
44
44
  code?: PROTO.ButtonRequest['code'] | 'ButtonRequest_FirmwareUpdate';
45
45
  }
46
46
 
47
+ export type PassphraseRequestPayload = {
48
+ existsAttachPinUser?: boolean;
49
+ };
50
+
47
51
  export interface DeviceButtonRequest {
48
52
  type: typeof DEVICE.BUTTON;
49
53
  payload: DeviceButtonRequestPayload & { device: Device | null };
@@ -66,7 +66,7 @@ export type UiRequestDeviceAction = {
66
66
  type: typeof UI_REQUEST.REQUEST_PIN;
67
67
  payload: {
68
68
  device: Device;
69
- type?: PROTO.PinMatrixRequestType | 'ButtonRequest_PinEntry';
69
+ type?: PROTO.PinMatrixRequestType | 'ButtonRequest_PinEntry' | 'ButtonRequest_AttachPin';
70
70
  };
71
71
  };
72
72
 
@@ -80,6 +80,7 @@ export interface UiRequestPassphrase {
80
80
  payload: {
81
81
  device: Device;
82
82
  passphraseState?: string;
83
+ existsAttachPinUser?: boolean;
83
84
  };
84
85
  }
85
86
 
@@ -18,6 +18,7 @@ export interface UiResponsePassphrase {
18
18
  payload: {
19
19
  value: string;
20
20
  passphraseOnDevice?: boolean;
21
+ attachPinOnDevice?: boolean;
21
22
  save?: boolean;
22
23
  };
23
24
  }
package/src/inject.ts CHANGED
@@ -138,6 +138,8 @@ export const createCoreApi = (
138
138
  call({ ...params, connectId, method: 'getPassphraseState' }),
139
139
  deviceCancel: (connectId, params) => call({ ...params, connectId, method: 'deviceCancel' }),
140
140
  deviceLock: (connectId, params) => call({ ...params, connectId, method: 'deviceLock' }),
141
+ deviceUnlock: (connectId, params) =>
142
+ call({ ...params, useEmptyPassphrase: true, connectId, method: 'deviceUnlock' }),
141
143
 
142
144
  getNextU2FCounter: (connectId, params) =>
143
145
  call({ ...params, connectId, method: 'getNextU2FCounter' }),
@@ -0,0 +1,4 @@
1
+ import { Features } from '@onekeyfe/hd-transport';
2
+ import type { CommonParams, Response } from '../params';
3
+
4
+ export declare function deviceUnlock(connectId: string, params?: CommonParams): Response<Features>;
@@ -35,6 +35,7 @@ import { deviceSupportFeatures } from './deviceSupportFeatures';
35
35
  import { deviceFullyUploadResource } from './deviceFullyUploadResource';
36
36
  import { deviceUpdateBootloader } from './deviceUpdateBootloader';
37
37
  import { deviceLock } from './deviceLock';
38
+ import { deviceUnlock } from './deviceUnlock';
38
39
  import { deviceCancel } from './deviceCancel';
39
40
 
40
41
  import { getNextU2FCounter } from './getNextU2FCounter';
@@ -214,6 +215,7 @@ export type CoreApi = {
214
215
  deviceFullyUploadResource: typeof deviceFullyUploadResource;
215
216
  deviceUpdateBootloader: typeof deviceUpdateBootloader;
216
217
  deviceLock: typeof deviceLock;
218
+ deviceUnlock: typeof deviceUnlock;
217
219
  deviceCancel: typeof deviceCancel;
218
220
  getNextU2FCounter: typeof getNextU2FCounter;
219
221
  setU2FCounter: typeof setU2FCounter;
@@ -37,6 +37,11 @@ export interface CommonParams {
37
37
  * Skip web device prompt
38
38
  */
39
39
  skipWebDevicePrompt?: boolean;
40
+
41
+ /**
42
+ * Skip passphrase check
43
+ */
44
+ skipPassphraseCheck?: boolean;
40
45
  }
41
46
 
42
47
  export type Params<T> = CommonParams & T & { bundle?: undefined };
@@ -14,7 +14,16 @@ export type ConnectSettings = {
14
14
  priority: number;
15
15
  trustedHost: boolean;
16
16
  supportedBrowser?: boolean;
17
- env: 'node' | 'web' | 'webextension' | 'electron' | 'react-native' | 'webusb' | 'lowlevel';
17
+ env:
18
+ | 'node'
19
+ | 'web'
20
+ | 'webextension'
21
+ | 'electron'
22
+ | 'react-native'
23
+ | 'webusb'
24
+ | 'emulator'
25
+ | 'desktop-web-ble'
26
+ | 'lowlevel';
18
27
  timestamp: number;
19
28
  isFrame?: boolean;
20
29
  preRelease?: boolean;