@onekeyfe/hd-core 1.2.8-alpha.5 → 1.2.8-alpha.6

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 (53) hide show
  1. package/README.md +27 -0
  2. package/__tests__/DeviceCommands.test.ts +13 -66
  3. package/__tests__/btc-derive-context-hash.test.ts +200 -0
  4. package/__tests__/core-error-output.test.ts +3 -34
  5. package/__tests__/device-lifecycle-events.test.ts +17 -64
  6. package/__tests__/device-pool-state.test.ts +0 -50
  7. package/__tests__/protocol-v2-bootloader-mode.test.ts +2 -31
  8. package/__tests__/protocol-v2.test.ts +47 -0
  9. package/__tests__/refresh-device-state.test.ts +17 -19
  10. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  11. package/dist/api/GetDeviceState.d.ts.map +1 -1
  12. package/dist/api/btc/BTCDeriveContextHash.d.ts +16 -0
  13. package/dist/api/btc/BTCDeriveContextHash.d.ts.map +1 -0
  14. package/dist/api/index.d.ts +1 -0
  15. package/dist/api/index.d.ts.map +1 -1
  16. package/dist/core/index.d.ts +1 -0
  17. package/dist/core/index.d.ts.map +1 -1
  18. package/dist/device/Device.d.ts +0 -2
  19. package/dist/device/Device.d.ts.map +1 -1
  20. package/dist/device/DeviceCommands.d.ts +4 -4
  21. package/dist/device/DeviceCommands.d.ts.map +1 -1
  22. package/dist/device/DevicePool.d.ts.map +1 -1
  23. package/dist/events/logBlockEvent.d.ts.map +1 -1
  24. package/dist/index.d.ts +14 -9
  25. package/dist/index.js +148 -38
  26. package/dist/inject.d.ts.map +1 -1
  27. package/dist/types/api/btcDeriveContextHash.d.ts +10 -0
  28. package/dist/types/api/btcDeriveContextHash.d.ts.map +1 -0
  29. package/dist/types/api/export.d.ts +1 -0
  30. package/dist/types/api/export.d.ts.map +1 -1
  31. package/dist/types/api/index.d.ts +2 -0
  32. package/dist/types/api/index.d.ts.map +1 -1
  33. package/dist/types/params.d.ts +0 -1
  34. package/dist/types/params.d.ts.map +1 -1
  35. package/dist/utils/patch.d.ts +1 -1
  36. package/dist/utils/patch.d.ts.map +1 -1
  37. package/package.json +4 -4
  38. package/src/api/FirmwareUpdateV4.ts +25 -8
  39. package/src/api/GetDeviceState.ts +5 -2
  40. package/src/api/btc/BTCDeriveContextHash.ts +90 -0
  41. package/src/api/index.ts +1 -0
  42. package/src/core/index.ts +7 -3
  43. package/src/data/messages/messages.json +51 -0
  44. package/src/device/Device.ts +1 -11
  45. package/src/device/DeviceCommands.ts +1 -15
  46. package/src/device/DevicePool.ts +2 -12
  47. package/src/events/core.ts +2 -2
  48. package/src/events/logBlockEvent.ts +1 -0
  49. package/src/inject.ts +2 -0
  50. package/src/types/api/btcDeriveContextHash.ts +15 -0
  51. package/src/types/api/export.ts +1 -0
  52. package/src/types/api/index.ts +2 -0
  53. package/src/types/params.ts +1 -1
package/src/core/index.ts CHANGED
@@ -23,6 +23,7 @@ import {
23
23
  createNeedUpgradeFirmwareHardwareError,
24
24
  createNewFirmwareForceUpdateHardwareError,
25
25
  createNewFirmwareUnReleaseHardwareError,
26
+ isBleStaleBondHardwareError,
26
27
  } from '@onekeyfe/hd-shared';
27
28
 
28
29
  import { LoggerNames, enableLog, getLogger, setLoggerPostMessage, wait } from '../utils';
@@ -1034,6 +1035,10 @@ export function isMissingDetectedProtocolV2Error(method: BaseMethod, error: unkn
1034
1035
  );
1035
1036
  }
1036
1037
 
1038
+ export function isTerminalBleStaleBondError(error: unknown) {
1039
+ return isBleStaleBondHardwareError(error);
1040
+ }
1041
+
1037
1042
  export function isDeviceIdentityMismatchError(error: unknown) {
1038
1043
  return (
1039
1044
  (error as { errorCode?: unknown })?.errorCode === HardwareErrorCode.DeviceCheckDeviceIdError
@@ -1272,7 +1277,6 @@ const ensureConnected = async (
1272
1277
  HardwareErrorCode.BridgeNotInstalled,
1273
1278
  HardwareErrorCode.BridgeTimeoutError,
1274
1279
  HardwareErrorCode.BridgeNeedsPermission,
1275
- HardwareErrorCode.WebUsbDeviceAccessError,
1276
1280
  ].includes(error.errorCode)
1277
1281
  ) {
1278
1282
  _deviceList = undefined;
@@ -1359,7 +1363,6 @@ const ensureConnected = async (
1359
1363
  HardwareErrorCode.DeviceDetectInBootloaderMode,
1360
1364
  HardwareErrorCode.BleCharacteristicNotifyChangeFailure,
1361
1365
  HardwareErrorCode.BridgeNeedsPermission,
1362
- HardwareErrorCode.WebUsbDeviceAccessError,
1363
1366
  HardwareErrorCode.DeviceInterruptedFromUser,
1364
1367
  HardwareErrorCode.CallQueueActionCancelled,
1365
1368
  ].includes(error.errorCode) ||
@@ -1367,6 +1370,7 @@ const ensureConnected = async (
1367
1370
  [HardwareErrorCode.BleDeviceDisconnected, HardwareErrorCode.PollingTimeout].includes(
1368
1371
  error.errorCode
1369
1372
  )) ||
1373
+ isTerminalBleStaleBondError(error) ||
1370
1374
  isDeviceIdentityMismatchError(error)
1371
1375
  ) {
1372
1376
  reject(error);
@@ -1589,7 +1593,7 @@ const onDeviceConnectHandler = (device: Device) => {
1589
1593
 
1590
1594
  const onDeviceDisconnectHandler = (device: Device) => {
1591
1595
  device.clearPreInitialized();
1592
- const deviceObject = device.toDisconnectMessageObject();
1596
+ const deviceObject = device.toMessageObject();
1593
1597
  if (!deviceObject) return;
1594
1598
  postMessage(createDeviceMessage(DEVICE.DISCONNECT, { device: deviceObject }));
1595
1599
  };
@@ -12485,6 +12485,8 @@
12485
12485
  "(has_bitcoin_only_values)": true
12486
12486
  },
12487
12487
  "values": {
12488
+ "MessageType_BabylonDeriveContextHash": 10054,
12489
+ "MessageType_BabylonDerivedContextHash": 10055,
12488
12490
  "MessageType_Initialize": 0,
12489
12491
  "MessageType_Ping": 1,
12490
12492
  "MessageType_Success": 2,
@@ -12949,6 +12951,55 @@
12949
12951
  "MessageType_UpgradeFileHeader": 10050
12950
12952
  }
12951
12953
  },
12954
+ "CanonicalBitcoinNetwork": {
12955
+ "values": {
12956
+ "BITCOIN_MAINNET": 0,
12957
+ "BITCOIN_TESTNET": 1,
12958
+ "BITCOIN_SIGNET": 2,
12959
+ "BITCOIN_REGTEST": 3
12960
+ }
12961
+ },
12962
+ "BabylonDeriveContextHash": {
12963
+ "fields": {
12964
+ "address_n": {
12965
+ "rule": "repeated",
12966
+ "type": "uint32",
12967
+ "id": 1,
12968
+ "options": {
12969
+ "packed": false
12970
+ }
12971
+ },
12972
+ "script_type": {
12973
+ "rule": "required",
12974
+ "type": "InputScriptType",
12975
+ "id": 2
12976
+ },
12977
+ "app_name": {
12978
+ "rule": "required",
12979
+ "type": "bytes",
12980
+ "id": 3
12981
+ },
12982
+ "context": {
12983
+ "rule": "required",
12984
+ "type": "bytes",
12985
+ "id": 4
12986
+ },
12987
+ "network": {
12988
+ "rule": "required",
12989
+ "type": "CanonicalBitcoinNetwork",
12990
+ "id": 5
12991
+ }
12992
+ }
12993
+ },
12994
+ "BabylonDerivedContextHash": {
12995
+ "fields": {
12996
+ "secret": {
12997
+ "rule": "required",
12998
+ "type": "bytes",
12999
+ "id": 1
13000
+ }
13001
+ }
13002
+ },
12952
13003
  "google": {
12953
13004
  "nested": {
12954
13005
  "protobuf": {
@@ -248,9 +248,6 @@ export class Device extends EventEmitter {
248
248
  /** Canonical device-state cache; legacy Features is a compatibility projection. */
249
249
  private stateStore = new DeviceStateStore();
250
250
 
251
- /** Retain the old public identity only for disconnect notifications after wipe. */
252
- private deviceBeforeWipe: DeviceTyped | null = null;
253
-
254
251
  /** Force the next initialization to reload DeviceInfo after reconnect or reboot. */
255
252
  private protocolV2StateNeedsReload = false;
256
253
 
@@ -354,8 +351,6 @@ export class Device extends EventEmitter {
354
351
  toMessageObject(): DeviceTyped | null {
355
352
  if (this.isUnacquired() || !this.features) return null;
356
353
 
357
- this.deviceBeforeWipe = null;
358
-
359
354
  const env = DataManager.getSettings('env');
360
355
  const deviceType = this.getCurrentDeviceType();
361
356
 
@@ -400,10 +395,6 @@ export class Device extends EventEmitter {
400
395
  };
401
396
  }
402
397
 
403
- toDisconnectMessageObject(): DeviceTyped | null {
404
- return this.toMessageObject() ?? this.deviceBeforeWipe;
405
- }
406
-
407
398
  /**
408
399
  * Device connect
409
400
  * @returns {Promise<boolean>}
@@ -1373,7 +1364,6 @@ export class Device extends EventEmitter {
1373
1364
  }
1374
1365
 
1375
1366
  invalidateAfterWipe() {
1376
- this.deviceBeforeWipe = this.toMessageObject() ?? this.deviceBeforeWipe;
1377
1367
  const deviceId = this.getCurrentDeviceId();
1378
1368
  if (deviceId) {
1379
1369
  deviceWalletSessionStore.deleteDevice(deviceId);
@@ -1811,7 +1801,7 @@ export class Device extends EventEmitter {
1811
1801
  // both allow and require cases might generate single unexpected mode
1812
1802
  if (!this.isUnacquired()) {
1813
1803
  // allow cases
1814
- if ((this.isBootloader() || this.isRomloader()) && !allow.includes(UI_REQUEST.BOOTLOADER)) {
1804
+ if (this.isBootloader() && !this.isProtocolV2() && !allow.includes(UI_REQUEST.BOOTLOADER)) {
1815
1805
  return UI_REQUEST.BOOTLOADER;
1816
1806
  }
1817
1807
  if (!this.isInitialized() && !allow.includes(UI_REQUEST.NOT_INITIALIZE)) {
@@ -549,16 +549,6 @@ export class DeviceCommands {
549
549
  this.device.isProtocolV2() &&
550
550
  DEVICE_CONTROL_CALLS.has(callType) &&
551
551
  subcode === DeviceErrorCode.DeviceError_Busy;
552
- const isProtocolV2PinCancelledBusyFailure =
553
- this.device.isProtocolV2() &&
554
- !DEVICE_SESSION_CALLS.has(callType) &&
555
- subcode === DeviceSessionErrorCode.DeviceSessionError_UserCancelled &&
556
- /^pin cancelled$/i.test(normalizedMessage);
557
- const isProtocolV2FirmwareUpdateBusyFailure =
558
- this.device.isProtocolV2() &&
559
- /^requested command not allowed while a firmware update is in progress$/i.test(
560
- normalizedMessage
561
- );
562
552
  const isLegacyProtocolV2LockedFailure =
563
553
  this.device.isProtocolV2() && /^device (?:is )?locked$/i.test(normalizedMessage);
564
554
  if (
@@ -616,11 +606,7 @@ export class DeviceCommands {
616
606
  subcode,
617
607
  firmwareMessage: message,
618
608
  });
619
- } else if (
620
- isProtocolV2DeviceBusyFailure ||
621
- isProtocolV2PinCancelledBusyFailure ||
622
- isProtocolV2FirmwareUpdateBusyFailure
623
- ) {
609
+ } else if (isProtocolV2DeviceBusyFailure) {
624
610
  error = ERRORS.TypedError(HardwareErrorCode.DeviceBusy, message, {
625
611
  failureCode: code,
626
612
  subcode,
@@ -114,11 +114,7 @@ export class DevicePool extends EventEmitter {
114
114
  const exist = canPathIdentifyDevice(cachedPath)
115
115
  ? descriptorList.find(d => d.path === cachedPath)
116
116
  : undefined;
117
- if (
118
- exist &&
119
- !initOptions?.forceProtocolDetection &&
120
- !(device.needReloadDevice && device.isUnacquired())
121
- ) {
117
+ if (exist && !initOptions?.forceProtocolDetection) {
122
118
  // Log.debug('find existed Device: ', connectId);
123
119
  device.updateDescriptor(exist, true);
124
120
  await this._refreshRuntimeState(device, initOptions);
@@ -174,13 +170,7 @@ export class DevicePool extends EventEmitter {
174
170
  const forceProtocolDetection = initOptions?.forceProtocolDetection === true;
175
171
  const isNewDevice = !cachedDevice;
176
172
  const device = cachedDevice ?? Device.fromDescriptor(descriptor);
177
- if (
178
- isNewDevice ||
179
- forceProtocolDetection ||
180
- (device.needReloadDevice && device.isUnacquired())
181
- ) {
182
- // Wipe invalidates state while the same USB path can remain discoverable.
183
- if (cachedDevice) device.updateDescriptor(descriptor, true);
173
+ if (isNewDevice || forceProtocolDetection) {
184
174
  device.deviceConnector = this.connector;
185
175
  // Search/discovery acquires outside Device.run(). Start a new attempt so
186
176
  // a previous user cancel does not hide this device from later searches.
@@ -54,9 +54,9 @@ export const parseMessage = (messageData: any): CoreMessage => {
54
54
  };
55
55
 
56
56
  export const createErrorMessage = (error: Error & { code?: string | number }): Unsuccessful => {
57
- let payload: Unsuccessful['payload'] = { error: error.message, code: error.code };
57
+ let payload = { error: error.message, code: error.code };
58
58
  if (error instanceof HardwareError) {
59
- payload = { error: error.message, code: error.errorCode, params: error.params };
59
+ payload = { error: error.message, code: error.errorCode };
60
60
  }
61
61
  return {
62
62
  success: false,
@@ -11,6 +11,7 @@ export const LogBlockEvent: Set<string> = new Set([
11
11
  // These resource/file APIs did not exist in 1.1.32. Skip the payload so
12
12
  // the log layer does not copy huge Base64 or binary data.
13
13
  const LogPayloadBlockMethod: Set<string> = new Set([
14
+ 'btcDeriveContextHash',
14
15
  'deviceUploadNft',
15
16
  'deviceUploadWallpaper',
16
17
  'uploadPortfolio',
package/src/inject.ts CHANGED
@@ -309,6 +309,8 @@ export const createCoreApi = (
309
309
  call({ ...params, connectId, deviceId, method: 'btcGetAddress' }),
310
310
  btcGetPublicKey: (connectId, deviceId, params) =>
311
311
  call({ ...params, connectId, deviceId, method: 'btcGetPublicKey' }),
312
+ btcDeriveContextHash: (connectId, deviceId, params) =>
313
+ call({ ...params, connectId, deviceId, method: 'btcDeriveContextHash' }),
312
314
  btcSignMessage: (connectId, deviceId, params) =>
313
315
  call({ ...params, connectId, deviceId, method: 'btcSignMessage' }),
314
316
  btcSignPsbt: (connectId, deviceId, params) =>
@@ -0,0 +1,15 @@
1
+ import type { BabylonDerivedContextHash } from '@onekeyfe/hd-transport';
2
+ import type { CommonParams, Response } from '../params';
3
+
4
+ export type BTCDeriveContextHashParams = {
5
+ path: string | number[];
6
+ appName: string;
7
+ context: string;
8
+ network: 'bitcoin-mainnet' | 'bitcoin-testnet' | 'bitcoin-signet' | 'bitcoin-regtest';
9
+ };
10
+
11
+ export declare function btcDeriveContextHash(
12
+ connectId: string,
13
+ deviceId: string,
14
+ params: CommonParams & BTCDeriveContextHashParams
15
+ ): Response<BabylonDerivedContextHash>;
@@ -1,5 +1,6 @@
1
1
  export type { BTCAddress, BTCGetAddressParams } from './btcGetAddress';
2
2
  export type { BTCPublicKey, BTCGetPublicKeyParams } from './btcGetPublicKey';
3
+ export type { BTCDeriveContextHashParams } from './btcDeriveContextHash';
3
4
  export type { BTCSignMessageParams } from './btcSignMessage';
4
5
  export type { BTCVerifyMessageParams } from './btcVerifyMessage';
5
6
  export type {
@@ -73,6 +73,7 @@ import type { evmSignTypedData } from './evmSignTypedData';
73
73
  import type { evmVerifyMessage } from './evmVerifyMessage';
74
74
  import type { btcGetAddress } from './btcGetAddress';
75
75
  import type { btcGetPublicKey } from './btcGetPublicKey';
76
+ import type { btcDeriveContextHash } from './btcDeriveContextHash';
76
77
  import type { btcSignMessage } from './btcSignMessage';
77
78
  import type { btcSignPsbt } from './btcSignPsbt';
78
79
  import type { btcSignTransaction } from './btcSignTransaction';
@@ -286,6 +287,7 @@ export type CoreApi = {
286
287
  */
287
288
  btcGetAddress: typeof btcGetAddress;
288
289
  btcGetPublicKey: typeof btcGetPublicKey;
290
+ btcDeriveContextHash: typeof btcDeriveContextHash;
289
291
  btcSignMessage: typeof btcSignMessage;
290
292
  btcSignPsbt: typeof btcSignPsbt;
291
293
  btcSignTransaction: typeof btcSignTransaction;
@@ -83,7 +83,7 @@ export type Params<T> = CommonParams & T & { bundle?: undefined };
83
83
 
84
84
  export interface Unsuccessful {
85
85
  success: false;
86
- payload: { error: string; code?: string | number; params?: Record<string, unknown> };
86
+ payload: { error: string; code?: string | number };
87
87
  }
88
88
 
89
89
  export interface Success<T> {