@onekeyfe/hd-core 1.2.8 → 1.2.10-alpha.1

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 (151) hide show
  1. package/README.md +27 -0
  2. package/__tests__/DeviceCommands.test.ts +66 -13
  3. package/__tests__/allNetworkGetAddress-privacy-networks.test.ts +78 -0
  4. package/__tests__/btc-derive-context-hash.test.ts +200 -0
  5. package/__tests__/core-dispose.test.ts +114 -1
  6. package/__tests__/core-error-output.test.ts +55 -3
  7. package/__tests__/device-connector-protocol.test.ts +5 -2
  8. package/__tests__/device-lifecycle-events.test.ts +191 -27
  9. package/__tests__/device-pool-state.test.ts +50 -0
  10. package/__tests__/firmware-update/firmware-artifact-source.test.ts +11 -0
  11. package/__tests__/logBlockEvent.test.ts +331 -9
  12. package/__tests__/logger.test.ts +18 -0
  13. package/__tests__/monero-get-address.test.ts +147 -0
  14. package/__tests__/monero-key-image-sync.test.ts +272 -0
  15. package/__tests__/monero-sign-transaction.test.ts +436 -0
  16. package/__tests__/protocol-v2-bootloader-mode.test.ts +43 -2
  17. package/__tests__/protocol-v2-resources.test.ts +14 -0
  18. package/__tests__/protocol-v2.test.ts +841 -46
  19. package/__tests__/protocolV2FileWrite.test.ts +454 -7
  20. package/__tests__/refresh-device-state.test.ts +19 -17
  21. package/__tests__/search-devices.test.ts +36 -0
  22. package/__tests__/sol-sign-offchain-message.test.ts +8 -0
  23. package/__tests__/usb-identity-probe.test.ts +358 -0
  24. package/__tests__/zcash-protobuf.test.ts +141 -0
  25. package/__tests__/zcash-sign-pczt.test.ts +446 -0
  26. package/dist/api/BaseMethod.d.ts.map +1 -1
  27. package/dist/api/FileWrite.d.ts.map +1 -1
  28. package/dist/api/FirmwareUpdateV4.d.ts +5 -0
  29. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  30. package/dist/api/GetDeviceState.d.ts.map +1 -1
  31. package/dist/api/SearchDevices.d.ts +21 -1
  32. package/dist/api/SearchDevices.d.ts.map +1 -1
  33. package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
  34. package/dist/api/btc/BTCDeriveContextHash.d.ts +16 -0
  35. package/dist/api/btc/BTCDeriveContextHash.d.ts.map +1 -0
  36. package/dist/api/firmware/FirmwareArtifactSource.d.ts.map +1 -1
  37. package/dist/api/helpers/pathUtils.d.ts +1 -0
  38. package/dist/api/helpers/pathUtils.d.ts.map +1 -1
  39. package/dist/api/helpers/protocolV2FileWrite.d.ts +5 -1
  40. package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
  41. package/dist/api/index.d.ts +7 -0
  42. package/dist/api/index.d.ts.map +1 -1
  43. package/dist/api/monero/MoneroGetAddress.d.ts +11 -0
  44. package/dist/api/monero/MoneroGetAddress.d.ts.map +1 -0
  45. package/dist/api/monero/MoneroGetWatchKey.d.ts +11 -0
  46. package/dist/api/monero/MoneroGetWatchKey.d.ts.map +1 -0
  47. package/dist/api/monero/MoneroKeyImageSync.d.ts +20 -0
  48. package/dist/api/monero/MoneroKeyImageSync.d.ts.map +1 -0
  49. package/dist/api/monero/MoneroSignTransaction.d.ts +17 -0
  50. package/dist/api/monero/MoneroSignTransaction.d.ts.map +1 -0
  51. package/dist/api/monero/helpers.d.ts +5 -0
  52. package/dist/api/monero/helpers.d.ts.map +1 -0
  53. package/dist/api/protocol-v2/DeviceReboot.d.ts.map +1 -1
  54. package/dist/api/protocol-v2/DeviceUploadNft.d.ts.map +1 -1
  55. package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts.map +1 -1
  56. package/dist/api/zcash/ZcashGetAddress.d.ts +12 -0
  57. package/dist/api/zcash/ZcashGetAddress.d.ts.map +1 -0
  58. package/dist/api/zcash/ZcashSignPczt.d.ts +16 -0
  59. package/dist/api/zcash/ZcashSignPczt.d.ts.map +1 -0
  60. package/dist/core/index.d.ts +3 -2
  61. package/dist/core/index.d.ts.map +1 -1
  62. package/dist/device/Device.d.ts +3 -0
  63. package/dist/device/Device.d.ts.map +1 -1
  64. package/dist/device/DeviceCommands.d.ts +4 -4
  65. package/dist/device/DeviceCommands.d.ts.map +1 -1
  66. package/dist/device/DevicePool.d.ts.map +1 -1
  67. package/dist/events/logBlockEvent.d.ts +10 -0
  68. package/dist/events/logBlockEvent.d.ts.map +1 -1
  69. package/dist/events/ui-request.d.ts +2 -0
  70. package/dist/events/ui-request.d.ts.map +1 -1
  71. package/dist/index.d.ts +196 -7
  72. package/dist/index.d.ts.map +1 -1
  73. package/dist/index.js +4363 -2792
  74. package/dist/inject.d.ts.map +1 -1
  75. package/dist/protocols/protocol-v2/resources.d.ts +1 -0
  76. package/dist/protocols/protocol-v2/resources.d.ts.map +1 -1
  77. package/dist/types/api/allNetworkGetAddress.d.ts +5 -1
  78. package/dist/types/api/allNetworkGetAddress.d.ts.map +1 -1
  79. package/dist/types/api/btcDeriveContextHash.d.ts +10 -0
  80. package/dist/types/api/btcDeriveContextHash.d.ts.map +1 -0
  81. package/dist/types/api/export.d.ts +7 -0
  82. package/dist/types/api/export.d.ts.map +1 -1
  83. package/dist/types/api/index.d.ts +14 -0
  84. package/dist/types/api/index.d.ts.map +1 -1
  85. package/dist/types/api/moneroGetAddress.d.ts +15 -0
  86. package/dist/types/api/moneroGetAddress.d.ts.map +1 -0
  87. package/dist/types/api/moneroGetWatchKey.d.ts +15 -0
  88. package/dist/types/api/moneroGetWatchKey.d.ts.map +1 -0
  89. package/dist/types/api/moneroKeyImageSync.d.ts +24 -0
  90. package/dist/types/api/moneroKeyImageSync.d.ts.map +1 -0
  91. package/dist/types/api/moneroSignTransaction.d.ts +32 -0
  92. package/dist/types/api/moneroSignTransaction.d.ts.map +1 -0
  93. package/dist/types/api/zcashGetAddress.d.ts +22 -0
  94. package/dist/types/api/zcashGetAddress.d.ts.map +1 -0
  95. package/dist/types/api/zcashSignPczt.d.ts +9 -0
  96. package/dist/types/api/zcashSignPczt.d.ts.map +1 -0
  97. package/dist/types/device.d.ts +10 -0
  98. package/dist/types/device.d.ts.map +1 -1
  99. package/dist/types/params.d.ts +1 -0
  100. package/dist/types/params.d.ts.map +1 -1
  101. package/dist/utils/logger.d.ts.map +1 -1
  102. package/dist/utils/patch.d.ts +1 -1
  103. package/dist/utils/patch.d.ts.map +1 -1
  104. package/package.json +4 -4
  105. package/src/api/BaseMethod.ts +2 -0
  106. package/src/api/FileWrite.ts +7 -1
  107. package/src/api/FirmwareUpdateV4.ts +366 -99
  108. package/src/api/GetDeviceState.ts +2 -5
  109. package/src/api/SearchDevices.ts +172 -7
  110. package/src/api/allnetwork/AllNetworkGetAddressBase.ts +38 -1
  111. package/src/api/btc/BTCDeriveContextHash.ts +90 -0
  112. package/src/api/firmware/FirmwareArtifactSource.ts +12 -3
  113. package/src/api/helpers/pathUtils.ts +23 -0
  114. package/src/api/helpers/protocolV2FileWrite.ts +382 -111
  115. package/src/api/index.ts +8 -0
  116. package/src/api/monero/MoneroGetAddress.ts +71 -0
  117. package/src/api/monero/MoneroGetWatchKey.ts +69 -0
  118. package/src/api/monero/MoneroKeyImageSync.ts +164 -0
  119. package/src/api/monero/MoneroSignTransaction.ts +319 -0
  120. package/src/api/monero/helpers.ts +28 -0
  121. package/src/api/protocol-v2/DeviceReboot.ts +2 -0
  122. package/src/api/protocol-v2/DeviceUploadNft.ts +6 -1
  123. package/src/api/protocol-v2/DeviceUploadWallpaper.ts +15 -1
  124. package/src/api/zcash/ZcashGetAddress.ts +119 -0
  125. package/src/api/zcash/ZcashSignPczt.ts +152 -0
  126. package/src/core/index.ts +52 -24
  127. package/src/data/messages/messages-protocol-v2.json +138 -1
  128. package/src/data/messages/messages.json +51 -0
  129. package/src/device/Device.ts +32 -4
  130. package/src/device/DeviceCommands.ts +15 -1
  131. package/src/device/DeviceConnector.ts +4 -4
  132. package/src/device/DevicePool.ts +12 -2
  133. package/src/events/core.ts +2 -2
  134. package/src/events/logBlockEvent.ts +57 -3
  135. package/src/events/ui-request.ts +2 -0
  136. package/src/index.ts +1 -0
  137. package/src/inject.ts +15 -0
  138. package/src/protocols/protocol-v2/resources.ts +6 -1
  139. package/src/types/api/allNetworkGetAddress.ts +9 -1
  140. package/src/types/api/btcDeriveContextHash.ts +15 -0
  141. package/src/types/api/export.ts +16 -0
  142. package/src/types/api/index.ts +22 -0
  143. package/src/types/api/moneroGetAddress.ts +27 -0
  144. package/src/types/api/moneroGetWatchKey.ts +28 -0
  145. package/src/types/api/moneroKeyImageSync.ts +45 -0
  146. package/src/types/api/moneroSignTransaction.ts +54 -0
  147. package/src/types/api/zcashGetAddress.ts +35 -0
  148. package/src/types/api/zcashSignPczt.ts +18 -0
  149. package/src/types/device.ts +18 -0
  150. package/src/types/params.ts +1 -1
  151. package/src/utils/logger.ts +4 -0
@@ -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": {
@@ -236,6 +236,9 @@ export class Device extends EventEmitter {
236
236
  */
237
237
  private deviceAcquired = false;
238
238
 
239
+ /** A completed BLE release left the physical link available for the next call. */
240
+ private releasedBleConnection = false;
241
+
239
242
  /**
240
243
  * Connection-attempt generation. interruptionFromUser() pins the current
241
244
  * attempt so a late acquire cannot finish, while the next public connect
@@ -248,6 +251,9 @@ export class Device extends EventEmitter {
248
251
  /** Canonical device-state cache; legacy Features is a compatibility projection. */
249
252
  private stateStore = new DeviceStateStore();
250
253
 
254
+ /** Retain the old public identity only for disconnect notifications after wipe. */
255
+ private deviceBeforeWipe: DeviceTyped | null = null;
256
+
251
257
  /** Force the next initialization to reload DeviceInfo after reconnect or reboot. */
252
258
  private protocolV2StateNeedsReload = false;
253
259
 
@@ -351,6 +357,8 @@ export class Device extends EventEmitter {
351
357
  toMessageObject(): DeviceTyped | null {
352
358
  if (this.isUnacquired() || !this.features) return null;
353
359
 
360
+ this.deviceBeforeWipe = null;
361
+
354
362
  const env = DataManager.getSettings('env');
355
363
  const deviceType = this.getCurrentDeviceType();
356
364
 
@@ -395,6 +403,10 @@ export class Device extends EventEmitter {
395
403
  };
396
404
  }
397
405
 
406
+ toDisconnectMessageObject(): DeviceTyped | null {
407
+ return this.toMessageObject() ?? this.deviceBeforeWipe;
408
+ }
409
+
398
410
  /**
399
411
  * Device connect
400
412
  * @returns {Promise<boolean>}
@@ -443,6 +455,7 @@ export class Device extends EventEmitter {
443
455
  ) {
444
456
  const attempt = this.connectionAttempt;
445
457
  this.throwIfInterruptedByUser();
458
+ this.releasedBleConnection = false;
446
459
  const env = DataManager.getSettings('env');
447
460
  const mainIdKey = DataManager.isBleConnect(env) ? 'id' : 'session';
448
461
  const previousProtocol = this.originalDescriptor.protocolType;
@@ -553,6 +566,7 @@ export class Device extends EventEmitter {
553
566
  (this.isUsedHere() && !this.keepSession && this.mainId) ||
554
567
  (this.mainId && DataManager.isBleConnect(env))
555
568
  ) {
569
+ this.releasedBleConnection = false;
556
570
  // wait for callback tasks to complete before releasing device
557
571
  if (this.pendingCallbackPromise) {
558
572
  try {
@@ -576,12 +590,24 @@ export class Device extends EventEmitter {
576
590
  }
577
591
  }
578
592
  try {
593
+ const deviceType = this.getCurrentDeviceType();
594
+ const keepBleConnection =
595
+ (env === 'react-native' || env === 'desktop-web-ble') &&
596
+ this.isProtocolV2() &&
597
+ (deviceType === EDeviceType.Pro2 || deviceType === EDeviceType.Neo);
579
598
  // BLE releases even when keepSession is set, so forward the intent.
580
- await this.deviceConnector?.release(this.mainId, false, this.keepSession);
581
- this.updateDescriptor({ session: null } as DeviceDescriptor);
599
+ await this.deviceConnector?.release(
600
+ this.mainId,
601
+ false,
602
+ this.keepSession || keepBleConnection
603
+ );
604
+ this.releasedBleConnection = keepBleConnection;
582
605
  } catch (err) {
583
606
  Log.error('[Device] release error: ', err);
584
607
  } finally {
608
+ // Core no longer owns a logical transport session after release starts,
609
+ // even if native cleanup must be retried by the transport.
610
+ this.updateDescriptor({ session: null } as DeviceDescriptor);
585
611
  this.needReloadDevice = true;
586
612
  }
587
613
  }
@@ -1360,10 +1386,12 @@ export class Device extends EventEmitter {
1360
1386
 
1361
1387
  markTransportDisconnected() {
1362
1388
  this.deviceAcquired = false;
1389
+ this.releasedBleConnection = false;
1363
1390
  this.invalidateProtocolV2RuntimeState();
1364
1391
  }
1365
1392
 
1366
1393
  invalidateAfterWipe() {
1394
+ this.deviceBeforeWipe = this.toMessageObject() ?? this.deviceBeforeWipe;
1367
1395
  const deviceId = this.getCurrentDeviceId();
1368
1396
  if (deviceId) {
1369
1397
  deviceWalletSessionStore.deleteDevice(deviceId);
@@ -1621,7 +1649,7 @@ export class Device extends EventEmitter {
1621
1649
  await commands?.cancelDevice?.().catch(cancelError => {
1622
1650
  Log.debug('Protocol V2 fallback cancel error', cancelError);
1623
1651
  });
1624
- } else if (!acquired) {
1652
+ } else if (!acquired && !this.releasedBleConnection) {
1625
1653
  // Abort setup without acquiring a session just to send Cancel.
1626
1654
  if (mainId && deviceConnector?.disconnect) {
1627
1655
  // The connector drops the link silently, so without this line a
@@ -1801,7 +1829,7 @@ export class Device extends EventEmitter {
1801
1829
  // both allow and require cases might generate single unexpected mode
1802
1830
  if (!this.isUnacquired()) {
1803
1831
  // allow cases
1804
- if (this.isBootloader() && !this.isProtocolV2() && !allow.includes(UI_REQUEST.BOOTLOADER)) {
1832
+ if ((this.isBootloader() || this.isRomloader()) && !allow.includes(UI_REQUEST.BOOTLOADER)) {
1805
1833
  return UI_REQUEST.BOOTLOADER;
1806
1834
  }
1807
1835
  if (!this.isInitialized() && !allow.includes(UI_REQUEST.NOT_INITIALIZE)) {
@@ -549,6 +549,16 @@ 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
+ );
552
562
  const isLegacyProtocolV2LockedFailure =
553
563
  this.device.isProtocolV2() && /^device (?:is )?locked$/i.test(normalizedMessage);
554
564
  if (
@@ -606,7 +616,11 @@ export class DeviceCommands {
606
616
  subcode,
607
617
  firmwareMessage: message,
608
618
  });
609
- } else if (isProtocolV2DeviceBusyFailure) {
619
+ } else if (
620
+ isProtocolV2DeviceBusyFailure ||
621
+ isProtocolV2PinCancelledBusyFailure ||
622
+ isProtocolV2FirmwareUpdateBusyFailure
623
+ ) {
610
624
  error = ERRORS.TypedError(HardwareErrorCode.DeviceBusy, message, {
611
625
  failureCode: code,
612
626
  subcode,
@@ -133,10 +133,10 @@ export default class DeviceConnector {
133
133
  : undefined;
134
134
  const detectedProtocol = acquiredProtocol ?? transport.getProtocolType(path);
135
135
  if (detectedProtocol !== expectedProtocol) {
136
- throw ERRORS.TypedError(
137
- HardwareErrorCode.RuntimeError,
138
- `Device protocol mismatch: expected ${expectedProtocol}, detected ${detectedProtocol}`
139
- );
136
+ throw ERRORS.TypedError(HardwareErrorCode.TransportProtocolMismatch, undefined, {
137
+ expectedProtocol,
138
+ detectedProtocol,
139
+ });
140
140
  }
141
141
  }
142
142
  return res;
@@ -114,7 +114,11 @@ export class DevicePool extends EventEmitter {
114
114
  const exist = canPathIdentifyDevice(cachedPath)
115
115
  ? descriptorList.find(d => d.path === cachedPath)
116
116
  : undefined;
117
- if (exist && !initOptions?.forceProtocolDetection) {
117
+ if (
118
+ exist &&
119
+ !initOptions?.forceProtocolDetection &&
120
+ !(device.needReloadDevice && device.isUnacquired())
121
+ ) {
118
122
  // Log.debug('find existed Device: ', connectId);
119
123
  device.updateDescriptor(exist, true);
120
124
  await this._refreshRuntimeState(device, initOptions);
@@ -170,7 +174,13 @@ export class DevicePool extends EventEmitter {
170
174
  const forceProtocolDetection = initOptions?.forceProtocolDetection === true;
171
175
  const isNewDevice = !cachedDevice;
172
176
  const device = cachedDevice ?? Device.fromDescriptor(descriptor);
173
- if (isNewDevice || forceProtocolDetection) {
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);
174
184
  device.deviceConnector = this.connector;
175
185
  // Search/discovery acquires outside Device.run(). Start a new attempt so
176
186
  // 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 = { error: error.message, code: error.code };
57
+ let payload: Unsuccessful['payload'] = { error: error.message, code: error.code };
58
58
  if (error instanceof HardwareError) {
59
- payload = { error: error.message, code: error.errorCode };
59
+ payload = { error: error.message, code: error.errorCode, params: error.params };
60
60
  }
61
61
  return {
62
62
  success: false,
@@ -8,14 +8,22 @@ export const LogBlockEvent: Set<string> = new Set([
8
8
  UI_RESPONSE.RECEIVE_PASSPHRASE,
9
9
  ]);
10
10
 
11
- // These resource/file APIs did not exist in 1.1.32. Skip the payload so
12
- // the log layer does not copy huge Base64 or binary data.
11
+ // Drop sensitive wallet payloads and large resource data before logger caches
12
+ // or log events can retain them, regardless of whether debug output is enabled.
13
13
  const LogPayloadBlockMethod: Set<string> = new Set([
14
+ 'btcDeriveContextHash',
15
+ 'btcSignMessage',
14
16
  'deviceUploadNft',
15
17
  'deviceUploadWallpaper',
16
18
  'uploadPortfolio',
17
19
  'fileWrite',
18
20
  'fileRead',
21
+ 'zcashGetAddress',
22
+ 'zcashSignPczt',
23
+ 'moneroGetAddress',
24
+ 'moneroGetWatchKey',
25
+ 'moneroKeyImageSync',
26
+ 'moneroSignTransaction',
19
27
  ]);
20
28
 
21
29
  export function getLogBlockLabel(message: unknown): string | undefined {
@@ -39,11 +47,57 @@ export function getLogBlockLabel(message: unknown): string | undefined {
39
47
  return undefined;
40
48
  }
41
49
 
50
+ // All-network results of these networks carry what their own address methods
51
+ // keep out of logs (viewing keys, private addresses).
52
+ const LogPayloadBlockNetwork: Set<string> = new Set(['zcash', 'xmr']);
53
+
54
+ type AllNetworkLogItem = { network?: string; success?: boolean; payload?: object | string } | null;
55
+
56
+ // A call response lists the results in `payload`; a loop callback carries one
57
+ // result, or all of them when finished, in `payload.data`.
58
+ type AllNetworkLogMessage = {
59
+ payload?: AllNetworkLogItem[] | { data?: AllNetworkLogItem | AllNetworkLogItem[] };
60
+ };
61
+
62
+ function redactAllNetworkItem(item: AllNetworkLogItem): AllNetworkLogItem {
63
+ if (!item || item.success === false || item.payload === undefined) return item;
64
+ return item.network && LogPayloadBlockNetwork.has(item.network)
65
+ ? { ...item, payload: '[REDACTED]' }
66
+ : item;
67
+ }
68
+
69
+ function redactAllNetworkItems(items: AllNetworkLogItem[]) {
70
+ const redacted = items.map(redactAllNetworkItem);
71
+ return redacted.some((item, index) => item !== items[index]) ? redacted : items;
72
+ }
73
+
74
+ // Returns `message` itself when nothing needs redacting.
75
+ function redactAllNetworkResults(message: AllNetworkLogMessage): AllNetworkLogMessage {
76
+ const { payload } = message;
77
+ if (Array.isArray(payload)) {
78
+ const items = redactAllNetworkItems(payload);
79
+ return items === payload ? message : { ...message, payload: items };
80
+ }
81
+ const data = payload?.data;
82
+ if (!data) return message;
83
+ const redacted = Array.isArray(data) ? redactAllNetworkItems(data) : redactAllNetworkItem(data);
84
+ return redacted === data ? message : { ...message, payload: { ...payload, data: redacted } };
85
+ }
86
+
42
87
  export function getSafeLogPayload(value: unknown, blockLabel?: string): unknown {
43
88
  if (blockLabel) {
44
89
  return { method: blockLabel, payload: '[REDACTED]' };
45
90
  }
46
- return value;
91
+ if (!value || typeof value !== 'object') return value;
92
+ return redactAllNetworkResults(value as AllNetworkLogMessage);
93
+ }
94
+
95
+ // A queued task holds its method's raw payload; redact it like the call.
96
+ export function getSafeLogTask<T extends { id?: number; method?: { payload?: unknown } }>(
97
+ task: T | undefined
98
+ ): T | { id?: number; method: string; payload: string } | undefined {
99
+ const blockLabel = getLogBlockLabel(task?.method?.payload);
100
+ return blockLabel ? { id: task?.id, method: blockLabel, payload: '[REDACTED]' } : task;
47
101
  }
48
102
 
49
103
  export function formatLogMethodLabel(label: string, methodName?: string): string {
@@ -211,6 +211,7 @@ export interface DeviceProgress {
211
211
  totalBytes?: number;
212
212
  rateBytesPerSecond?: number;
213
213
  elapsedMs?: number;
214
+ retryCount?: number;
214
215
  };
215
216
  }
216
217
 
@@ -218,6 +219,7 @@ export interface PreviousAddressResult {
218
219
  type: typeof UI_REQUEST.PREVIOUS_ADDRESS_RESULT;
219
220
  payload: {
220
221
  device: Device;
222
+ method: string;
221
223
  data: {
222
224
  address?: string;
223
225
  path?: string;
package/src/index.ts CHANGED
@@ -21,6 +21,7 @@ export { executeCallback, cleanupCallback };
21
21
  export { preloadSessionCache } from './device/Device';
22
22
  export { projectFeatures as projectDeviceStateFeatures } from './device/DeviceStateProjector';
23
23
  export { getMethodSupportedProtocols } from './api/utils';
24
+ export { probeUsbDeviceIdentitiesWithTransport } from './api/SearchDevices';
24
25
  export {
25
26
  getFirmwareUpdateHostBindingGeneration,
26
27
  registerFirmwareUpdateHostBinding,
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) =>
@@ -502,4 +504,17 @@ export const createCoreApi = (
502
504
  call({ ...params, connectId, deviceId, method: 'neoGetAddress' }),
503
505
  neoSignTransaction: (connectId, deviceId, params) =>
504
506
  call({ ...params, connectId, deviceId, method: 'neoSignTransaction' }),
507
+ zcashGetAddress: (connectId, deviceId, params) =>
508
+ call({ ...params, connectId, deviceId, method: 'zcashGetAddress' }),
509
+ zcashSignPczt: (connectId, deviceId, params) =>
510
+ call({ ...params, connectId, deviceId, method: 'zcashSignPczt' }),
511
+
512
+ moneroGetAddress: (connectId, deviceId, params) =>
513
+ call({ ...params, connectId, deviceId, method: 'moneroGetAddress' }),
514
+ moneroGetWatchKey: (connectId, deviceId, params) =>
515
+ call({ ...params, connectId, deviceId, method: 'moneroGetWatchKey' }),
516
+ moneroKeyImageSync: (connectId, deviceId, params) =>
517
+ call({ ...params, connectId, deviceId, method: 'moneroKeyImageSync' }),
518
+ moneroSignTransaction: (connectId, deviceId, params) =>
519
+ call({ ...params, connectId, deviceId, method: 'moneroSignTransaction' }),
505
520
  });
@@ -7,6 +7,8 @@ export const PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_PATH =
7
7
  export const PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_STAGING_PATH = `${PROTOCOL_V2_BOOT_RESOURCE_PACKAGE_PATH}.staging`;
8
8
  export const PROTOCOL_V2_ROM_PARAMS_PACKAGE_PATH = 'vol0:/loaders/rom/params.okpkg';
9
9
  export const PROTOCOL_V2_RESOURCE_PACKAGE_HEADER_SIZE = 0x5f90;
10
+ // Installed-package comparison only needs the prefix through the header hash.
11
+ export const PROTOCOL_V2_RESOURCE_PACKAGE_COMPARE_SIZE = 0x280;
10
12
 
11
13
  const PROTOCOL_V2_RESOURCE_PACKAGE_HEADER_VERSION = 1;
12
14
  const PROTOCOL_V2_RESOURCE_PACKAGE_FLEXIBLE_OFFSET = 0x6c;
@@ -123,7 +125,7 @@ export function parseProtocolV2ResourcePackageHeader(
123
125
  bytes: Uint8Array,
124
126
  packageSize: number
125
127
  ): ProtocolV2ResourcePackageHeader {
126
- if (bytes.byteLength < PROTOCOL_V2_RESOURCE_PACKAGE_HEADER_SIZE) {
128
+ if (bytes.byteLength < PROTOCOL_V2_RESOURCE_PACKAGE_COMPARE_SIZE) {
127
129
  throw new Error('Pro2 RESOURCE package is shorter than its header');
128
130
  }
129
131
  const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
@@ -169,5 +171,8 @@ export function parseProtocolV2ResourcePackage(
169
171
  binary: ArrayBuffer | Uint8Array
170
172
  ): ProtocolV2ResourcePackageHeader {
171
173
  const bytes = binary instanceof Uint8Array ? binary : new Uint8Array(binary);
174
+ if (bytes.byteLength < PROTOCOL_V2_RESOURCE_PACKAGE_HEADER_SIZE) {
175
+ throw new Error('Pro2 RESOURCE package is shorter than its header');
176
+ }
172
177
  return parseProtocolV2ResourcePackageHeader(bytes, bytes.byteLength);
173
178
  }
@@ -34,7 +34,9 @@ export type INetwork =
34
34
  | 'nostr'
35
35
  | 'benfen'
36
36
  | 'neo'
37
- | 'stellar';
37
+ | 'stellar'
38
+ | 'xmr'
39
+ | 'zcash';
38
40
 
39
41
  export type CommonResponseParams = {
40
42
  path: string;
@@ -66,6 +68,12 @@ type AllNetworkAddressPayload =
66
68
  // Nostr public key (bech32)
67
69
  npub?: string;
68
70
  }
71
+ | {
72
+ // Zcash
73
+ address: string;
74
+ ufvk?: string;
75
+ seedFingerprint?: string;
76
+ }
69
77
  | {
70
78
  // Cardano
71
79
  addressParameters: CardanoAddressParameters;
@@ -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 {
@@ -226,3 +227,18 @@ export type { BenfenAddress, BenfenGetAddressParams } from './benfenGetAddress';
226
227
  export type { BenfenPublicKey, BenfenGetPublicKeyParams } from './benfenGetPublicKey';
227
228
  export type { BenfenSignMessageParams } from './benfenSignMessage';
228
229
  export type { BenfenSignedTx, BenfenSignTransactionParams } from './benfenSignTransaction';
230
+ export type { ZcashAddress, ZcashGetAddressParams } from './zcashGetAddress';
231
+ export type { ZcashSignedPczt, ZcashSignPcztParams } from './zcashSignPczt';
232
+
233
+ export type { MoneroAddress, MoneroGetAddressParams } from './moneroGetAddress';
234
+ export type { MoneroGetWatchKeyParams, MoneroWatchKey } from './moneroGetWatchKey';
235
+ export type {
236
+ MoneroEncryptedKeyImage,
237
+ MoneroKeyImageSyncParams,
238
+ MoneroKeyImageSyncResult,
239
+ MoneroKeyImageTransfer,
240
+ } from './moneroKeyImageSync';
241
+ export type {
242
+ MoneroSignTransactionParams,
243
+ MoneroSignTransactionResult,
244
+ } from './moneroSignTransaction';
@@ -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';
@@ -153,6 +154,12 @@ import type { benfenSignTransaction } from './benfenSignTransaction';
153
154
  import type { benfenSignMessage } from './benfenSignMessage';
154
155
  import type { neoGetAddress } from './neoGetAddress';
155
156
  import type { neoSignTransaction } from './neoSignTransaction';
157
+ import type { zcashGetAddress } from './zcashGetAddress';
158
+ import type { zcashSignPczt } from './zcashSignPczt';
159
+ import type { moneroGetAddress } from './moneroGetAddress';
160
+ import type { moneroGetWatchKey } from './moneroGetWatchKey';
161
+ import type { moneroKeyImageSync } from './moneroKeyImageSync';
162
+ import type { moneroSignTransaction } from './moneroSignTransaction';
156
163
  import type { ConnectSettings } from '../settings';
157
164
  import type { HardwareConnectProtocol } from '@onekeyfe/hd-shared';
158
165
 
@@ -286,6 +293,7 @@ export type CoreApi = {
286
293
  */
287
294
  btcGetAddress: typeof btcGetAddress;
288
295
  btcGetPublicKey: typeof btcGetPublicKey;
296
+ btcDeriveContextHash: typeof btcDeriveContextHash;
289
297
  btcSignMessage: typeof btcSignMessage;
290
298
  btcSignPsbt: typeof btcSignPsbt;
291
299
  btcSignTransaction: typeof btcSignTransaction;
@@ -470,4 +478,18 @@ export type CoreApi = {
470
478
  */
471
479
  neoGetAddress: typeof neoGetAddress;
472
480
  neoSignTransaction: typeof neoSignTransaction;
481
+
482
+ /**
483
+ * Zcash
484
+ */
485
+ zcashGetAddress: typeof zcashGetAddress;
486
+ zcashSignPczt: typeof zcashSignPczt;
487
+
488
+ /**
489
+ * Monero
490
+ */
491
+ moneroGetAddress: typeof moneroGetAddress;
492
+ moneroGetWatchKey: typeof moneroGetWatchKey;
493
+ moneroKeyImageSync: typeof moneroKeyImageSync;
494
+ moneroSignTransaction: typeof moneroSignTransaction;
473
495
  };
@@ -0,0 +1,27 @@
1
+ import type { CommonParams, Response } from '../params';
2
+
3
+ export type MoneroAddress = {
4
+ path: string;
5
+ // Primary address of the account, base58
6
+ address: string;
7
+ };
8
+
9
+ export type MoneroGetAddressParams = {
10
+ // Account path, m/44'/128'/account'
11
+ path: string | number[];
12
+ showOnOneKey?: boolean;
13
+ // 0 mainnet, 1 testnet, 2 stagenet
14
+ networkType?: number;
15
+ };
16
+
17
+ export declare function moneroGetAddress(
18
+ connectId: string,
19
+ deviceId: string,
20
+ params: CommonParams & MoneroGetAddressParams
21
+ ): Response<MoneroAddress>;
22
+
23
+ export declare function moneroGetAddress(
24
+ connectId: string,
25
+ deviceId: string,
26
+ params: CommonParams & { bundle?: MoneroGetAddressParams[] }
27
+ ): Response<Array<MoneroAddress>>;
@@ -0,0 +1,28 @@
1
+ import type { CommonParams, Response } from '../params';
2
+
3
+ export type MoneroWatchKey = {
4
+ path: string;
5
+ // Private view key, hex
6
+ watchKey: string;
7
+ // Primary address of the account, base58
8
+ address: string;
9
+ };
10
+
11
+ export type MoneroGetWatchKeyParams = {
12
+ // Account path, m/44'/128'/account'
13
+ path: string | number[];
14
+ // 0 mainnet, 1 testnet, 2 stagenet
15
+ networkType?: number;
16
+ };
17
+
18
+ export declare function moneroGetWatchKey(
19
+ connectId: string,
20
+ deviceId: string,
21
+ params: CommonParams & MoneroGetWatchKeyParams
22
+ ): Response<MoneroWatchKey>;
23
+
24
+ export declare function moneroGetWatchKey(
25
+ connectId: string,
26
+ deviceId: string,
27
+ params: CommonParams & { bundle?: MoneroGetWatchKeyParams[] }
28
+ ): Response<Array<MoneroWatchKey>>;
@@ -0,0 +1,45 @@
1
+ import type { CommonParams, Response } from '../params';
2
+
3
+ // One owned output, as wallet2 describes it to the device. Keys are 32-byte hex.
4
+ export type MoneroKeyImageTransfer = {
5
+ // Output public key
6
+ outKey: string;
7
+ // Transaction public key R
8
+ txPubKey: string;
9
+ // Additional tx public keys: the one for this output, or the whole list
10
+ additionalTxPubKeys?: string[];
11
+ // Index of the output within its transaction
12
+ internalOutputIndex: number;
13
+ // Receiving subaddress index; omitted means 0 (primary address)
14
+ subAddrMajor?: number;
15
+ subAddrMinor?: number;
16
+ };
17
+
18
+ // ChaCha20-Poly1305 under encKey, hex.
19
+ export type MoneroEncryptedKeyImage = {
20
+ // 12-byte nonce
21
+ iv: string;
22
+ // Ciphertext of key image || signature c || signature r, then the 16-byte tag
23
+ blob: string;
24
+ };
25
+
26
+ export type MoneroKeyImageSyncResult = {
27
+ // Key that decrypts every blob, hex
28
+ encKey: string;
29
+ // One entry per transfer, in request order
30
+ keyImages: MoneroEncryptedKeyImage[];
31
+ };
32
+
33
+ export type MoneroKeyImageSyncParams = {
34
+ // Account path, m/44'/128'/account'
35
+ path: string | number[];
36
+ // 0 mainnet, 1 testnet, 2 stagenet
37
+ networkType?: number;
38
+ transfers: MoneroKeyImageTransfer[];
39
+ };
40
+
41
+ export declare function moneroKeyImageSync(
42
+ connectId: string,
43
+ deviceId: string,
44
+ params: CommonParams & MoneroKeyImageSyncParams
45
+ ): Response<MoneroKeyImageSyncResult>;