@onekeyfe/hd-core 1.1.27-alpha.41 → 1.1.27-alpha.43

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 (176) hide show
  1. package/__tests__/DeviceCommands.test.ts +99 -0
  2. package/__tests__/evmLedgerLegacySafety.test.ts +261 -0
  3. package/__tests__/logBlockEvent.test.ts +37 -0
  4. package/__tests__/preInitialize.test.ts +22 -0
  5. package/__tests__/protocol-v2.test.ts +139 -27
  6. package/dist/api/BaseMethod.d.ts +7 -1
  7. package/dist/api/BaseMethod.d.ts.map +1 -1
  8. package/dist/api/FirmwareUpdateV3.d.ts.map +1 -1
  9. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  10. package/dist/api/GetPassphraseState.d.ts.map +1 -1
  11. package/dist/api/alephium/AlephiumSignMessage.d.ts.map +1 -1
  12. package/dist/api/alephium/AlephiumSignTransaction.d.ts.map +1 -1
  13. package/dist/api/algo/AlgoSignTransaction.d.ts.map +1 -1
  14. package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
  15. package/dist/api/aptos/AptosSignInMessage.d.ts.map +1 -1
  16. package/dist/api/aptos/AptosSignMessage.d.ts.map +1 -1
  17. package/dist/api/aptos/AptosSignTransaction.d.ts.map +1 -1
  18. package/dist/api/benfen/BenfenSignMessage.d.ts.map +1 -1
  19. package/dist/api/benfen/BenfenSignTransaction.d.ts.map +1 -1
  20. package/dist/api/btc/BTCSignMessage.d.ts.map +1 -1
  21. package/dist/api/btc/BTCSignPsbt.d.ts.map +1 -1
  22. package/dist/api/btc/BTCSignTransaction.d.ts.map +1 -1
  23. package/dist/api/cardano/CardanoSignMessage.d.ts.map +1 -1
  24. package/dist/api/cardano/CardanoSignTransaction.d.ts.map +1 -1
  25. package/dist/api/conflux/ConfluxSignMessage.d.ts.map +1 -1
  26. package/dist/api/conflux/ConfluxSignMessageCIP23.d.ts.map +1 -1
  27. package/dist/api/conflux/ConfluxSignTransaction.d.ts.map +1 -1
  28. package/dist/api/cosmos/CosmosSignTransaction.d.ts.map +1 -1
  29. package/dist/api/device/DeviceLock.d.ts.map +1 -1
  30. package/dist/api/device/PreInitialize.d.ts +6 -0
  31. package/dist/api/device/PreInitialize.d.ts.map +1 -0
  32. package/dist/api/dynex/DnxSignTransaction.d.ts.map +1 -1
  33. package/dist/api/evm/EVMSignMessage.d.ts.map +1 -1
  34. package/dist/api/evm/EVMSignMessageEIP712.d.ts.map +1 -1
  35. package/dist/api/evm/EVMSignTransaction.d.ts.map +1 -1
  36. package/dist/api/evm/EVMSignTypedData.d.ts.map +1 -1
  37. package/dist/api/filecoin/FilecoinSignTransaction.d.ts.map +1 -1
  38. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts +2 -10
  39. package/dist/api/firmware/FirmwareUpdateBaseMethod.d.ts.map +1 -1
  40. package/dist/api/index.d.ts +1 -0
  41. package/dist/api/index.d.ts.map +1 -1
  42. package/dist/api/kaspa/KaspaSignTransaction.d.ts.map +1 -1
  43. package/dist/api/near/NearSignTransaction.d.ts.map +1 -1
  44. package/dist/api/nem/NEMSignTransaction.d.ts.map +1 -1
  45. package/dist/api/neo/NeoSignTransaction.d.ts.map +1 -1
  46. package/dist/api/nervos/NervosSignTransaction.d.ts.map +1 -1
  47. package/dist/api/nexa/NexaSignTransaction.d.ts.map +1 -1
  48. package/dist/api/nostr/NostrSignEvent.d.ts.map +1 -1
  49. package/dist/api/nostr/NostrSignSchnorr.d.ts.map +1 -1
  50. package/dist/api/polkadot/PolkadotSignTransaction.d.ts.map +1 -1
  51. package/dist/api/protocol-v2/DeviceGetOnboardingStatus.d.ts +1 -1
  52. package/dist/api/protocol-v2/DeviceGetOnboardingStatus.d.ts.map +1 -1
  53. package/dist/api/protocol-v2/FilesystemDiskControl.d.ts +1 -1
  54. package/dist/api/scdo/ScdoSignMessage.d.ts.map +1 -1
  55. package/dist/api/scdo/ScdoSignTransaction.d.ts.map +1 -1
  56. package/dist/api/solana/SolSignMessage.d.ts.map +1 -1
  57. package/dist/api/solana/SolSignOffchainMessage.d.ts.map +1 -1
  58. package/dist/api/solana/SolSignTransaction.d.ts.map +1 -1
  59. package/dist/api/starcoin/StarcoinSignMessage.d.ts.map +1 -1
  60. package/dist/api/starcoin/StarcoinSignTransaction.d.ts.map +1 -1
  61. package/dist/api/stellar/StellarSignTransaction.d.ts.map +1 -1
  62. package/dist/api/sui/SuiGetAddress.d.ts +3 -0
  63. package/dist/api/sui/SuiGetAddress.d.ts.map +1 -1
  64. package/dist/api/sui/SuiGetPublicKey.d.ts +3 -0
  65. package/dist/api/sui/SuiGetPublicKey.d.ts.map +1 -1
  66. package/dist/api/sui/SuiSignMessage.d.ts +3 -0
  67. package/dist/api/sui/SuiSignMessage.d.ts.map +1 -1
  68. package/dist/api/sui/SuiSignTransaction.d.ts +3 -0
  69. package/dist/api/sui/SuiSignTransaction.d.ts.map +1 -1
  70. package/dist/api/ton/TonGetAddress.d.ts +3 -0
  71. package/dist/api/ton/TonGetAddress.d.ts.map +1 -1
  72. package/dist/api/ton/TonSignData.d.ts +5 -0
  73. package/dist/api/ton/TonSignData.d.ts.map +1 -1
  74. package/dist/api/ton/TonSignMessage.d.ts +3 -0
  75. package/dist/api/ton/TonSignMessage.d.ts.map +1 -1
  76. package/dist/api/ton/TonSignProof.d.ts +3 -0
  77. package/dist/api/ton/TonSignProof.d.ts.map +1 -1
  78. package/dist/api/tron/TronSignMessage.d.ts.map +1 -1
  79. package/dist/api/tron/TronSignTransaction.d.ts.map +1 -1
  80. package/dist/api/xrp/XrpSignTransaction.d.ts.map +1 -1
  81. package/dist/core/PollingStateManager.d.ts +8 -0
  82. package/dist/core/PollingStateManager.d.ts.map +1 -0
  83. package/dist/core/RequestQueue.d.ts +1 -1
  84. package/dist/core/RequestQueue.d.ts.map +1 -1
  85. package/dist/core/index.d.ts.map +1 -1
  86. package/dist/device/Device.d.ts +17 -2
  87. package/dist/device/Device.d.ts.map +1 -1
  88. package/dist/events/logBlockEvent.d.ts +1 -0
  89. package/dist/events/logBlockEvent.d.ts.map +1 -1
  90. package/dist/index.d.ts +25 -5
  91. package/dist/index.js +928 -407
  92. package/dist/types/api/index.d.ts +2 -0
  93. package/dist/types/api/index.d.ts.map +1 -1
  94. package/dist/types/api/preInitialize.d.ts +3 -0
  95. package/dist/types/api/preInitialize.d.ts.map +1 -0
  96. package/dist/types/api/protocolV2.d.ts +2 -2
  97. package/dist/types/api/protocolV2.d.ts.map +1 -1
  98. package/dist/types/params.d.ts +1 -0
  99. package/dist/types/params.d.ts.map +1 -1
  100. package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
  101. package/dist/utils/patch.d.ts +1 -1
  102. package/dist/utils/patch.d.ts.map +1 -1
  103. package/package.json +4 -4
  104. package/src/api/BaseMethod.ts +82 -2
  105. package/src/api/FirmwareUpdateV3.ts +0 -4
  106. package/src/api/FirmwareUpdateV4.ts +1 -19
  107. package/src/api/GetPassphraseState.ts +4 -3
  108. package/src/api/alephium/AlephiumSignMessage.ts +1 -0
  109. package/src/api/alephium/AlephiumSignTransaction.ts +1 -0
  110. package/src/api/algo/AlgoSignTransaction.ts +1 -0
  111. package/src/api/allnetwork/AllNetworkGetAddressBase.ts +8 -0
  112. package/src/api/aptos/AptosSignInMessage.ts +1 -0
  113. package/src/api/aptos/AptosSignMessage.ts +1 -0
  114. package/src/api/aptos/AptosSignTransaction.ts +1 -0
  115. package/src/api/benfen/BenfenSignMessage.ts +1 -0
  116. package/src/api/benfen/BenfenSignTransaction.ts +1 -0
  117. package/src/api/btc/BTCSignMessage.ts +1 -0
  118. package/src/api/btc/BTCSignPsbt.ts +1 -0
  119. package/src/api/btc/BTCSignTransaction.ts +1 -0
  120. package/src/api/cardano/CardanoSignMessage.ts +1 -0
  121. package/src/api/cardano/CardanoSignTransaction.ts +1 -0
  122. package/src/api/conflux/ConfluxSignMessage.ts +1 -0
  123. package/src/api/conflux/ConfluxSignMessageCIP23.ts +1 -0
  124. package/src/api/conflux/ConfluxSignTransaction.ts +1 -0
  125. package/src/api/cosmos/CosmosSignTransaction.ts +1 -0
  126. package/src/api/device/DeviceLock.ts +1 -3
  127. package/src/api/device/PreInitialize.ts +41 -0
  128. package/src/api/dynex/DnxSignTransaction.ts +1 -0
  129. package/src/api/evm/EVMSignMessage.ts +2 -0
  130. package/src/api/evm/EVMSignMessageEIP712.ts +1 -0
  131. package/src/api/evm/EVMSignTransaction.ts +2 -0
  132. package/src/api/evm/EVMSignTypedData.ts +3 -1
  133. package/src/api/filecoin/FilecoinSignTransaction.ts +1 -0
  134. package/src/api/firmware/FirmwareUpdateBaseMethod.ts +4 -27
  135. package/src/api/index.ts +1 -0
  136. package/src/api/kaspa/KaspaSignTransaction.ts +1 -0
  137. package/src/api/near/NearSignTransaction.ts +1 -0
  138. package/src/api/nem/NEMSignTransaction.ts +1 -0
  139. package/src/api/neo/NeoSignTransaction.ts +1 -0
  140. package/src/api/nervos/NervosSignTransaction.ts +1 -0
  141. package/src/api/nexa/NexaSignTransaction.ts +2 -0
  142. package/src/api/nostr/NostrSignEvent.ts +1 -0
  143. package/src/api/nostr/NostrSignSchnorr.ts +1 -0
  144. package/src/api/polkadot/PolkadotSignTransaction.ts +1 -0
  145. package/src/api/protocol-v2/DeviceGetOnboardingStatus.ts +1 -5
  146. package/src/api/scdo/ScdoSignMessage.ts +1 -0
  147. package/src/api/scdo/ScdoSignTransaction.ts +1 -0
  148. package/src/api/solana/SolSignMessage.ts +1 -0
  149. package/src/api/solana/SolSignOffchainMessage.ts +1 -0
  150. package/src/api/solana/SolSignTransaction.ts +1 -0
  151. package/src/api/starcoin/StarcoinSignMessage.ts +1 -0
  152. package/src/api/starcoin/StarcoinSignTransaction.ts +1 -0
  153. package/src/api/stellar/StellarSignTransaction.ts +1 -0
  154. package/src/api/sui/SuiGetAddress.ts +3 -0
  155. package/src/api/sui/SuiGetPublicKey.ts +3 -0
  156. package/src/api/sui/SuiSignMessage.ts +4 -0
  157. package/src/api/sui/SuiSignTransaction.ts +4 -0
  158. package/src/api/ton/TonGetAddress.ts +3 -0
  159. package/src/api/ton/TonSignData.ts +11 -3
  160. package/src/api/ton/TonSignMessage.ts +4 -0
  161. package/src/api/ton/TonSignProof.ts +4 -0
  162. package/src/api/tron/TronSignMessage.ts +1 -0
  163. package/src/api/tron/TronSignTransaction.ts +1 -0
  164. package/src/api/xrp/XrpSignTransaction.ts +1 -0
  165. package/src/core/PollingStateManager.ts +47 -0
  166. package/src/core/RequestQueue.ts +10 -3
  167. package/src/core/index.ts +153 -34
  168. package/src/data/messages/messages-protocol-v2.json +489 -268
  169. package/src/device/Device.ts +73 -16
  170. package/src/events/logBlockEvent.ts +23 -0
  171. package/src/inject.ts +1 -1
  172. package/src/types/api/index.ts +2 -0
  173. package/src/types/api/preInitialize.ts +3 -0
  174. package/src/types/api/protocolV2.ts +2 -2
  175. package/src/types/params.ts +5 -0
  176. package/src/utils/deviceFeaturesUtils.ts +8 -17
@@ -8,16 +8,19 @@ import { supportInputPinOnSoftware, supportModifyHomescreen } from '../utils/dev
8
8
  import { createDeviceMessage } from '../events/device';
9
9
  import { UI_REQUEST } from '../constants/ui-request';
10
10
  import { DEVICE, FIRMWARE, createFirmwareMessage, createUiMessage } from '../events';
11
+ import { getHDPath, toHardened } from './helpers/pathUtils';
11
12
  import { getBleFirmwareReleaseInfo, getFirmwareReleaseInfo } from './firmware/releaseHelper';
12
13
  import {
13
14
  LoggerNames,
14
15
  getDeviceFirmwareVersion,
16
+ getDeviceType,
15
17
  getFirmwareType,
16
18
  getLogger,
17
19
  getMethodVersionRange,
18
20
  isMethodVersionRangeUnsupported,
19
21
  } from '../utils';
20
22
  import { generateInstanceId } from '../utils/tracing';
23
+ import { DeviceModelToTypes } from '../types';
21
24
 
22
25
  import type { Device } from '../device/Device';
23
26
  import type DeviceConnector from '../device/DeviceConnector';
@@ -28,6 +31,31 @@ import type { CoreContext } from '../core';
28
31
 
29
32
  const Log = getLogger(LoggerNames.Method);
30
33
 
34
+ const isEvmLedgerLegacyPathWithHighIndex = (path: unknown) => {
35
+ let addressN: number[] | undefined;
36
+ if (typeof path === 'string') {
37
+ try {
38
+ addressN = getHDPath(path);
39
+ } catch {
40
+ return false;
41
+ }
42
+ } else if (Array.isArray(path)) {
43
+ addressN = path.map((item: unknown) => Number(item));
44
+ }
45
+
46
+ return (
47
+ Array.isArray(addressN) &&
48
+ addressN.length === 4 &&
49
+ addressN[0] === toHardened(44) &&
50
+ addressN[1] === toHardened(60) &&
51
+ addressN[2] === toHardened(0) &&
52
+ addressN[3] > 1 &&
53
+ addressN[3] < toHardened(0)
54
+ );
55
+ };
56
+
57
+ const EVM_LEDGER_LEGACY_METHODS = ['evmGetAddress', 'evmGetPublicKey'];
58
+
31
59
  export abstract class BaseMethod<Params = undefined> {
32
60
  responseID: number;
33
61
 
@@ -106,6 +134,28 @@ export abstract class BaseMethod<Params = undefined> {
106
134
  */
107
135
  skipForceUpdateCheck = false;
108
136
 
137
+ /** Allow skipping Initialize (sign methods only; never getAddress/getPublicKey). @default false */
138
+ allowUsePreInitialize = false;
139
+
140
+ /** Pre-warm signal method (fire-and-forget; core dedups + hangs up). @default false */
141
+ isPreWarmSignal = false;
142
+
143
+ /** Pre-warm dedup TTL (ms) */
144
+ preWarmTtl = 60 * 1000;
145
+
146
+ /** Pre-warm dedup key: connectId + passphraseState + method name */
147
+ getPreWarmKey(): string {
148
+ const payload = (this.payload ?? {}) as {
149
+ connectId?: string;
150
+ passphraseState?: string;
151
+ };
152
+ return [
153
+ this.connectId ?? payload.connectId ?? '',
154
+ payload.passphraseState ?? '',
155
+ this.name,
156
+ ].join('|');
157
+ }
158
+
109
159
  /**
110
160
  * 严格检查设备是否支持该方法,不支持则抛出错误
111
161
  * @experiment 默认不严格检查,如果需要严格检查,则需要设置为 true
@@ -118,6 +168,8 @@ export abstract class BaseMethod<Params = undefined> {
118
168
 
119
169
  context?: CoreContext;
120
170
 
171
+ temporarySafetyCheckPrompted = false;
172
+
121
173
  constructor(message: { id?: number; payload: any }) {
122
174
  const { payload } = message;
123
175
  this.name = payload.method;
@@ -245,11 +297,32 @@ export abstract class BaseMethod<Params = undefined> {
245
297
  }
246
298
  }
247
299
 
300
+ private shouldPromptSafetyCheckForEvmLedgerLegacyPath() {
301
+ if (!EVM_LEDGER_LEGACY_METHODS.includes(this.name)) {
302
+ return false;
303
+ }
304
+
305
+ const deviceType = getDeviceType(this.device.features);
306
+ if (!DeviceModelToTypes.model_touch.includes(deviceType)) {
307
+ return false;
308
+ }
309
+
310
+ const paths = Array.isArray(this.payload?.bundle)
311
+ ? this.payload.bundle.map((item: { path?: unknown }) => item?.path)
312
+ : [this.payload?.path];
313
+
314
+ return paths.some(isEvmLedgerLegacyPathWithHighIndex);
315
+ }
316
+
248
317
  /**
249
- * Automatic check safety_check level for Kovan, Ropsten, Rinkeby, Goerli test networks.
250
- * @returns {void}
318
+ * Automatic check safety_check level for selected calls that require temporary relaxed checks.
319
+ * @returns whether a temporary safety check prompt was applied.
251
320
  */
252
321
  async checkSafetyLevelOnTestNet() {
322
+ if (this.temporarySafetyCheckPrompted) {
323
+ return false;
324
+ }
325
+
253
326
  let checkFlag = false;
254
327
  // 3 - Ropsten, 4 - Rinkeby, 5 - Goerli, 420 - Optimism Goerli, 11155111 - zkSync Sepolia
255
328
  if (
@@ -258,12 +331,19 @@ export abstract class BaseMethod<Params = undefined> {
258
331
  ) {
259
332
  checkFlag = true;
260
333
  }
334
+ if (this.shouldPromptSafetyCheckForEvmLedgerLegacyPath()) {
335
+ checkFlag = true;
336
+ }
261
337
  if (checkFlag && this.device.features?.safety_checks === 'Strict') {
262
338
  Log.debug('will change safety_checks level');
263
339
  await this.device.commands.typedCall('ApplySettings', 'Success', {
264
340
  safety_checks: 'PromptTemporarily',
265
341
  });
342
+ this.temporarySafetyCheckPrompted = true;
343
+ return true;
266
344
  }
345
+
346
+ return false;
267
347
  }
268
348
 
269
349
  dispose() {}
@@ -265,7 +265,6 @@ export default class FirmwareUpdateV3 extends FirmwareUpdateBaseMethod<FirmwareU
265
265
  }
266
266
 
267
267
  this.postTipMessage(FirmwareUpdateTipMessage.StartTransferData);
268
- const transferStartTime = Date.now();
269
268
 
270
269
  // Process resource zip contents
271
270
  if (resourceBinary) {
@@ -280,7 +279,6 @@ export default class FirmwareUpdateV3 extends FirmwareUpdateBaseMethod<FirmwareU
280
279
  filePath: `0:res/${name}`,
281
280
  processedSize,
282
281
  totalSize,
283
- transferStartTime,
284
282
  });
285
283
  }
286
284
  }
@@ -292,7 +290,6 @@ export default class FirmwareUpdateV3 extends FirmwareUpdateBaseMethod<FirmwareU
292
290
  filePath: `0:boot/bootloader.bin`,
293
291
  processedSize,
294
292
  totalSize,
295
- transferStartTime,
296
293
  });
297
294
  }
298
295
 
@@ -305,7 +302,6 @@ export default class FirmwareUpdateV3 extends FirmwareUpdateBaseMethod<FirmwareU
305
302
  filePath: `0:updates/${fwbinary.fileName}`,
306
303
  processedSize,
307
304
  totalSize,
308
- transferStartTime,
309
305
  });
310
306
  }
311
307
  }
@@ -353,7 +353,6 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
353
353
  if (bootloaderBinary) totalSize += bootloaderBinary.byteLength;
354
354
 
355
355
  this.postTipMessage(FirmwareUpdateTipMessage.StartTransferData);
356
- const transferStartTime = Date.now();
357
356
 
358
357
  const targets: Array<{ target_id: number; path: string }> = [];
359
358
 
@@ -371,7 +370,6 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
371
370
  filePath: `${resourcePath}${name}`,
372
371
  processedSize,
373
372
  totalSize,
374
- transferStartTime,
375
373
  });
376
374
  }
377
375
  }
@@ -388,7 +386,6 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
388
386
  filePath: bootloaderPath,
389
387
  processedSize,
390
388
  totalSize,
391
- transferStartTime,
392
389
  });
393
390
  targets.push({
394
391
  target_id: ProtocolV2FirmwareTargetType.TARGET_BOOTLOADER,
@@ -403,7 +400,6 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
403
400
  filePath: firmwarePath,
404
401
  processedSize,
405
402
  totalSize,
406
- transferStartTime,
407
403
  });
408
404
  targets.push({
409
405
  target_id: protocolV2FileNameToTargetId(fwbinary.fileName),
@@ -624,12 +620,10 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
624
620
  filePath,
625
621
  processedSize,
626
622
  totalSize,
627
- transferStartTime = Date.now(),
628
623
  }: PROTO.FirmwareUpload & {
629
624
  filePath: string;
630
625
  processedSize?: number;
631
626
  totalSize?: number;
632
- transferStartTime?: number;
633
627
  }) {
634
628
  const chunkSize = this.getProtocolV2FirmwareChunkSize();
635
629
  let offset = 0;
@@ -663,19 +657,7 @@ export default class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod<FirmwareU
663
657
  );
664
658
  }
665
659
  offset = nextOffset;
666
- const elapsedMs = Date.now() - transferStartTime;
667
- const transferredBytes =
668
- totalSize !== undefined && processedSize !== undefined
669
- ? Math.min(processedSize + offset, totalSize)
670
- : offset;
671
- const totalBytes = totalSize ?? payload.byteLength;
672
- this.postProgressMessage(getUploadProgress(offset), 'transferData', {
673
- transferredBytes,
674
- totalBytes,
675
- rateBytesPerSecond:
676
- elapsedMs > 0 ? Math.round((transferredBytes / elapsedMs) * 1000) : undefined,
677
- elapsedMs,
678
- });
660
+ this.postProgressMessage(getUploadProgress(offset), 'transferData');
679
661
  }
680
662
 
681
663
  return totalSize !== undefined ? (processedSize ?? 0) + payload.byteLength : 0;
@@ -20,15 +20,16 @@ export default class GetPassphraseState extends BaseMethod {
20
20
  expectPassphraseState: this.payload.passphraseState,
21
21
  onlyMainPin: this.payload.useEmptyPassphrase,
22
22
  allowCreateAttachPin: this.payload.allowCreateAttachPin,
23
- });
23
+ });
24
24
 
25
25
  const { features } = this.device;
26
- const isPro2 = getDeviceType(features) === EDeviceType.Pro2;
27
26
  const passphraseProtection = features?.passphrase_protection ?? null;
27
+ const deviceType = getDeviceType(features);
28
+ const isProSeries = deviceType === EDeviceType.Pro || deviceType === EDeviceType.Pro2;
28
29
 
29
30
  // refresh device info
30
31
  return Promise.resolve({
31
- passphrase_state: isPro2 || passphraseProtection === true ? passphraseState : undefined,
32
+ passphrase_state: isProSeries || passphraseProtection === true ? passphraseState : undefined,
32
33
  session_id: newSession ?? features?.session_id ?? undefined,
33
34
  unlocked_attach_pin: unlockedAttachPin ?? features?.unlocked_attach_pin,
34
35
  passphrase_protection: passphraseProtection,
@@ -11,6 +11,7 @@ export default class AlephiumSignMessage extends BaseMethod<HardwareAlephiumSign
11
11
  init() {
12
12
  this.checkDeviceId = true;
13
13
  this.allowDeviceMode = [...this.allowDeviceMode, UI_REQUEST.NOT_INITIALIZE];
14
+ this.allowUsePreInitialize = true;
14
15
 
15
16
  // check payload
16
17
  validateParams(this.payload, [
@@ -18,6 +18,7 @@ export default class AlephiumSignTransaction extends BaseMethod<HardwareAlephium
18
18
  init() {
19
19
  this.checkDeviceId = true;
20
20
  this.allowDeviceMode = [...this.allowDeviceMode, UI_REQUEST.NOT_INITIALIZE];
21
+ this.allowUsePreInitialize = true;
21
22
 
22
23
  // check payload
23
24
  validateParams(this.payload, [
@@ -12,6 +12,7 @@ export default class AlgoSignTransaction extends BaseMethod<HardwareAlgorandSign
12
12
  init() {
13
13
  this.checkDeviceId = true;
14
14
  this.allowDeviceMode = [...this.allowDeviceMode];
15
+ this.allowUsePreInitialize = true;
15
16
 
16
17
  // check payload
17
18
  validateParams(this.payload, [
@@ -376,6 +376,14 @@ export default abstract class AllNetworkGetAddressBase extends BaseMethod<
376
376
  this.device.on(DEVICE.PASSPHRASE, onSignalAbort);
377
377
 
378
378
  preCheckDeviceSupport(this.device, method);
379
+ if (this.temporarySafetyCheckPrompted) {
380
+ method.temporarySafetyCheckPrompted = true;
381
+ } else {
382
+ const appliedTemporarySafetyCheck = await method.checkSafetyLevelOnTestNet();
383
+ if (appliedTemporarySafetyCheck) {
384
+ this.temporarySafetyCheckPrompted = true;
385
+ }
386
+ }
379
387
 
380
388
  const response = await method.run();
381
389
 
@@ -10,6 +10,7 @@ export default class AptosSignInMessage extends BaseMethod<AptosSignSIWAMessage>
10
10
  init() {
11
11
  this.checkDeviceId = true;
12
12
  this.allowDeviceMode = [...this.allowDeviceMode, UI_REQUEST.NOT_INITIALIZE];
13
+ this.allowUsePreInitialize = true;
13
14
 
14
15
  // check payload
15
16
  validateParams(this.payload, [
@@ -10,6 +10,7 @@ export default class AptosSignMessage extends BaseMethod<HardwareAptosSignMessag
10
10
  init() {
11
11
  this.checkDeviceId = true;
12
12
  this.allowDeviceMode = [...this.allowDeviceMode, UI_REQUEST.NOT_INITIALIZE];
13
+ this.allowUsePreInitialize = true;
13
14
 
14
15
  // check payload
15
16
  validateParams(this.payload, [
@@ -10,6 +10,7 @@ export default class AptosSignTransaction extends BaseMethod<HardwareAptosSignTx
10
10
  init() {
11
11
  this.checkDeviceId = true;
12
12
  this.allowDeviceMode = [...this.allowDeviceMode, UI_REQUEST.NOT_INITIALIZE];
13
+ this.allowUsePreInitialize = true;
13
14
 
14
15
  // check payload
15
16
  validateParams(this.payload, [
@@ -11,6 +11,7 @@ export default class BenfenSignMessage extends BaseMethod<HardwareBenfenSignMess
11
11
  init() {
12
12
  this.checkDeviceId = true;
13
13
  this.allowDeviceMode = [...this.allowDeviceMode, UI_REQUEST.NOT_INITIALIZE];
14
+ this.allowUsePreInitialize = true;
14
15
 
15
16
  validateParams(this.payload, [
16
17
  { name: 'path', required: true },
@@ -14,6 +14,7 @@ export default class BenfenSignTransaction extends BaseMethod<BenfenSignTx> {
14
14
  init() {
15
15
  this.checkDeviceId = true;
16
16
  this.allowDeviceMode = [...this.allowDeviceMode, UI_REQUEST.NOT_INITIALIZE];
17
+ this.allowUsePreInitialize = true;
17
18
 
18
19
  validateParams(this.payload, [
19
20
  { name: 'path', required: true },
@@ -12,6 +12,7 @@ export default class BTCSignMessage extends BaseMethod<SignMessage> {
12
12
  init() {
13
13
  this.checkDeviceId = true;
14
14
  this.allowDeviceMode = [...this.allowDeviceMode, UI_REQUEST.NOT_INITIALIZE];
15
+ this.allowUsePreInitialize = true;
15
16
 
16
17
  validateParams(this.payload, [
17
18
  { name: 'path', required: true },
@@ -13,6 +13,7 @@ export default class BTCSignPsbt extends BaseMethod<SignPsbt> {
13
13
  init() {
14
14
  this.checkDeviceId = true;
15
15
  this.allowDeviceMode = [...this.allowDeviceMode, UI_REQUEST.NOT_INITIALIZE];
16
+ this.allowUsePreInitialize = true;
16
17
 
17
18
  validateParams(this.payload, [
18
19
  { name: 'psbt', type: 'hexString', required: true },
@@ -29,6 +29,7 @@ export default class BTCSignTransaction extends BaseMethod<Params> {
29
29
  init() {
30
30
  this.checkDeviceId = true;
31
31
  this.allowDeviceMode = [...this.allowDeviceMode, UI_REQUEST.NOT_INITIALIZE];
32
+ this.allowUsePreInitialize = true;
32
33
 
33
34
  validateParams(this.payload, [
34
35
  { name: 'coin', type: 'string', required: true },
@@ -14,6 +14,7 @@ export default class CardanoSignMessage extends BaseMethod<CardanoSignMessagePar
14
14
  init() {
15
15
  this.checkDeviceId = true;
16
16
  this.allowDeviceMode = [...this.allowDeviceMode, UI_REQUEST.NOT_INITIALIZE];
17
+ this.allowUsePreInitialize = true;
17
18
 
18
19
  const { payload } = this;
19
20
  validateParams(payload, [
@@ -49,6 +49,7 @@ export default class CardanoSignTransaction extends BaseMethod<any> {
49
49
  init() {
50
50
  this.checkDeviceId = true;
51
51
  this.allowDeviceMode = [...this.allowDeviceMode, UI_REQUEST.NOT_INITIALIZE];
52
+ this.allowUsePreInitialize = true;
52
53
 
53
54
  this.hasBundle = !!this.payload?.bundle;
54
55
 
@@ -9,6 +9,7 @@ import type { ConfluxSignMessage as HardwareConfluxSignMessage } from '@onekeyfe
9
9
  export default class ConfluxSignMessage extends BaseMethod<HardwareConfluxSignMessage> {
10
10
  init() {
11
11
  this.allowDeviceMode = [...this.allowDeviceMode, UI_REQUEST.NOT_INITIALIZE];
12
+ this.allowUsePreInitialize = true;
12
13
 
13
14
  // check payload
14
15
  validateParams(this.payload, [
@@ -9,6 +9,7 @@ import type { ConfluxSignMessageCIP23 as HardwareConfluxSignMessageCIP23 } from
9
9
  export default class ConfluxSignMessageCIP23 extends BaseMethod<HardwareConfluxSignMessageCIP23> {
10
10
  init() {
11
11
  this.allowDeviceMode = [...this.allowDeviceMode, UI_REQUEST.NOT_INITIALIZE];
12
+ this.allowUsePreInitialize = true;
12
13
 
13
14
  validateParams(this.payload, [
14
15
  { name: 'path', required: true },
@@ -22,6 +22,7 @@ export default class ConfluxSignTransaction extends BaseMethod {
22
22
 
23
23
  init() {
24
24
  this.allowDeviceMode = [...this.allowDeviceMode, UI_REQUEST.NOT_INITIALIZE];
25
+ this.allowUsePreInitialize = true;
25
26
 
26
27
  validateParams(this.payload, [
27
28
  { name: 'path', required: true },
@@ -14,6 +14,7 @@ export default class CosmosSignTransaction extends BaseMethod<HardwareCosmosSign
14
14
  init() {
15
15
  this.checkDeviceId = true;
16
16
  this.allowDeviceMode = [...this.allowDeviceMode];
17
+ this.allowUsePreInitialize = true;
17
18
 
18
19
  // check payload
19
20
  validateParams(this.payload, [
@@ -8,8 +8,6 @@ export default class DeviceLock extends BaseMethod<LockDevice> {
8
8
  }
9
9
 
10
10
  async run() {
11
- const res = await this.device.commands.typedCall('LockDevice', 'Success');
12
-
13
- return Promise.resolve(res.message);
11
+ return this.device.lockDevice();
14
12
  }
15
13
  }
@@ -0,0 +1,41 @@
1
+ import { BaseMethod } from '../BaseMethod';
2
+ import { LoggerNames, getLogger } from '../../utils';
3
+
4
+ import type { InitOptions } from '../../device/Device';
5
+
6
+ // Core prefix (@onekey/hd-core) so the host app's LOG_EVENT bridge forwards
7
+ // this into the collected hardware log scope (like [PRE-INIT][HIT]/[MISS]).
8
+ const Log = getLogger(LoggerNames.Core);
9
+
10
+ const parseInitOptions = (payload?: {
11
+ initSession?: boolean;
12
+ passphraseState?: string;
13
+ deriveCardano?: boolean;
14
+ }): InitOptions => ({
15
+ initSession: payload?.initSession,
16
+ passphraseState: payload?.passphraseState,
17
+ deriveCardano: payload?.deriveCardano,
18
+ });
19
+
20
+ export default class PreInitialize extends BaseMethod {
21
+ init() {
22
+ this.skipForceUpdateCheck = true;
23
+ this.useDevicePassphraseState = false;
24
+ // Fire-and-forget warm-up signal (core dedups + hangs up for the next call)
25
+ this.isPreWarmSignal = true;
26
+ }
27
+
28
+ async run() {
29
+ try {
30
+ await this.device.preInitialize(parseInitOptions(this.payload));
31
+ if (this.device.hasDeviceAcquire()) {
32
+ await this.device.release();
33
+ }
34
+ return true;
35
+ } catch {
36
+ this.device.clearPreInitialized();
37
+ Log.debug('[PRE-INIT][FAILED]');
38
+ return false;
39
+ }
40
+ }
41
+ }
@@ -17,6 +17,7 @@ export default class DnxSignTransaction extends BaseMethod<DnxSignTx> {
17
17
  init() {
18
18
  this.checkDeviceId = true;
19
19
  this.allowDeviceMode = [...this.allowDeviceMode, UI_REQUEST.NOT_INITIALIZE];
20
+ this.allowUsePreInitialize = true;
20
21
 
21
22
  const { payload } = this;
22
23
  // init params
@@ -13,12 +13,14 @@ export default class EVMSignMessage extends BaseMethod<EthereumSignMessageOneKey
13
13
  init() {
14
14
  this.checkDeviceId = true;
15
15
  this.allowDeviceMode = [...this.allowDeviceMode, UI_REQUEST.NOT_INITIALIZE];
16
+ this.allowUsePreInitialize = true;
16
17
 
17
18
  // check payload
18
19
  validateParams(this.payload, [
19
20
  { name: 'path', required: true },
20
21
  { name: 'messageHex', type: 'hexString', required: true },
21
22
  { name: 'chainId', type: 'number' },
23
+ { name: 'usePreInitialize', type: 'boolean' },
22
24
  ]);
23
25
 
24
26
  const { path, messageHex, chainId } = this.payload;
@@ -14,6 +14,7 @@ export default class EVMSignMessageEIP712 extends BaseMethod<EthereumSignMessage
14
14
  init() {
15
15
  this.checkDeviceId = true;
16
16
  this.allowDeviceMode = [...this.allowDeviceMode, UI_REQUEST.NOT_INITIALIZE];
17
+ this.allowUsePreInitialize = true;
17
18
 
18
19
  validateParams(this.payload, [
19
20
  { name: 'path', required: true },
@@ -46,10 +46,12 @@ export default class EVMSignTransaction extends BaseMethod {
46
46
  init() {
47
47
  this.checkDeviceId = true;
48
48
  this.allowDeviceMode = [...this.allowDeviceMode, UI_REQUEST.NOT_INITIALIZE];
49
+ this.allowUsePreInitialize = true;
49
50
 
50
51
  validateParams(this.payload, [
51
52
  { name: 'path', required: true },
52
53
  { name: 'transaction', type: 'object', required: true },
54
+ { name: 'usePreInitialize', type: 'boolean' },
53
55
  ]);
54
56
  const { path, transaction } = this.payload;
55
57
  this.addressN = validatePath(path, 3);
@@ -52,6 +52,7 @@ export default class EVMSignTypedData extends BaseMethod<EVMSignTypedDataParams>
52
52
  init() {
53
53
  this.checkDeviceId = true;
54
54
  this.allowDeviceMode = [...this.allowDeviceMode, UI_REQUEST.NOT_INITIALIZE];
55
+ this.allowUsePreInitialize = true;
55
56
 
56
57
  validateParams(this.payload, [
57
58
  { name: 'path', required: true },
@@ -60,6 +61,7 @@ export default class EVMSignTypedData extends BaseMethod<EVMSignTypedDataParams>
60
61
  { name: 'domainHash', type: 'hexString' },
61
62
  { name: 'messageHash', type: 'hexString' },
62
63
  { name: 'chainId', type: 'number' },
64
+ { name: 'usePreInitialize', type: 'boolean' },
63
65
  ]);
64
66
 
65
67
  const { path, data, metamaskV4Compat, domainHash, messageHash, chainId } = this.payload;
@@ -181,7 +183,7 @@ export default class EVMSignTypedData extends BaseMethod<EVMSignTypedDataParams>
181
183
  } else if (typeof memberData === 'object' && memberData !== null) {
182
184
  const memberTypeDefinition = types[memberTypeName][index];
183
185
  memberTypeName = memberTypeDefinition.type;
184
- memberData = memberData[memberTypeDefinition.name];
186
+ memberData = (memberData as Record<string, unknown>)[memberTypeDefinition.name];
185
187
  } else {
186
188
  // TODO
187
189
  }
@@ -12,6 +12,7 @@ export default class FilecoinSignTransaction extends BaseMethod<HardwareFilecoin
12
12
  init() {
13
13
  this.checkDeviceId = true;
14
14
  this.allowDeviceMode = [...this.allowDeviceMode];
15
+ this.allowUsePreInitialize = true;
15
16
 
16
17
  // check payload
17
18
  validateParams(this.payload, [
@@ -28,13 +28,6 @@ const Log = getLogger(LoggerNames.Method);
28
28
  const SESSION_ERROR = 'session not found';
29
29
  const FIRMWARE_UPDATE_CONFIRM = 'Firmware install confirmed';
30
30
 
31
- type FirmwareProgressMetadata = {
32
- transferredBytes?: number;
33
- totalBytes?: number;
34
- rateBytesPerSecond?: number;
35
- elapsedMs?: number;
36
- };
37
-
38
31
  const isDeviceDisconnectedError = (error: unknown) => {
39
32
  const message = error instanceof Error ? error.message : String(error ?? '');
40
33
  return (
@@ -89,17 +82,12 @@ export class FirmwareUpdateBaseMethod<Params> extends BaseMethod<Params> {
89
82
  * @description Post the progress message
90
83
  * @param progress Post the percentage of the progress
91
84
  */
92
- postProgressMessage = (
93
- progress: number,
94
- progressType: IFirmwareUpdateProgressType,
95
- metadata: FirmwareProgressMetadata = {}
96
- ) => {
85
+ postProgressMessage = (progress: number, progressType: IFirmwareUpdateProgressType) => {
97
86
  this.postMessage(
98
87
  createUiMessage(UI_REQUEST.FIRMWARE_PROGRESS, {
99
88
  device: this.device.toMessageObject() as KnownDevice,
100
89
  progress,
101
90
  progressType,
102
- ...metadata,
103
91
  })
104
92
  );
105
93
  };
@@ -337,12 +325,10 @@ export class FirmwareUpdateBaseMethod<Params> extends BaseMethod<Params> {
337
325
  filePath,
338
326
  processedSize,
339
327
  totalSize,
340
- transferStartTime = Date.now(),
341
328
  }: PROTO.FirmwareUpload & {
342
329
  filePath: string;
343
330
  processedSize?: number;
344
331
  totalSize?: number;
345
- transferStartTime?: number;
346
332
  }) {
347
333
  if (!filePath.startsWith('0:')) {
348
334
  throw new Error('filePath must start with 0:');
@@ -352,6 +338,7 @@ export class FirmwareUpdateBaseMethod<Params> extends BaseMethod<Params> {
352
338
  const chunkSize = 1024 * perPackageSize;
353
339
  const totalChunks = Math.ceil(payload.byteLength / chunkSize);
354
340
  let offset = 0;
341
+ let currentFileProcessed = 0;
355
342
 
356
343
  for (let i = 0; i < totalChunks; i++) {
357
344
  const chunkStart = i * chunkSize;
@@ -363,7 +350,7 @@ export class FirmwareUpdateBaseMethod<Params> extends BaseMethod<Params> {
363
350
  // Calculate progress based on whether we're tracking overall progress or single file progress
364
351
  let progress: number;
365
352
  if (totalSize !== undefined && processedSize !== undefined) {
366
- const currentFileProcessed = processedSize + chunkEnd;
353
+ currentFileProcessed = processedSize + chunkEnd;
367
354
  progress = Math.min(Math.ceil((currentFileProcessed / totalSize) * 100), 99);
368
355
  } else {
369
356
  progress = Math.min(Math.ceil(((i + 1) / totalChunks) * 100), 99);
@@ -379,17 +366,7 @@ export class FirmwareUpdateBaseMethod<Params> extends BaseMethod<Params> {
379
366
  );
380
367
  // @ts-expect-error
381
368
  offset += writeRes.message.processed_byte;
382
- const elapsedMs = Date.now() - transferStartTime;
383
- const transferredBytes =
384
- totalSize !== undefined && processedSize !== undefined ? processedSize + offset : offset;
385
- const totalBytes = totalSize ?? payload.byteLength;
386
- this.postProgressMessage(progress, 'transferData', {
387
- transferredBytes,
388
- totalBytes,
389
- rateBytesPerSecond:
390
- elapsedMs > 0 ? Math.round((transferredBytes / elapsedMs) * 1000) : undefined,
391
- elapsedMs,
392
- });
369
+ this.postProgressMessage(progress, 'transferData');
393
370
  }
394
371
 
395
372
  // Return processed size only if we're tracking overall progress
package/src/api/index.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export { default as testInitializeDeviceDuration } from './test/TestInitializeDeviceDuration';
2
+ export { default as preInitialize } from './device/PreInitialize';
2
3
 
3
4
  export { default as searchDevices } from './SearchDevices';
4
5
  export { default as getFeatures } from './GetFeatures';
@@ -22,6 +22,7 @@ export default class KaspaSignTransaction extends BaseMethod<KaspaSignTransactio
22
22
  init() {
23
23
  this.checkDeviceId = true;
24
24
  this.allowDeviceMode = [...this.allowDeviceMode, UI_REQUEST.NOT_INITIALIZE];
25
+ this.allowUsePreInitialize = true;
25
26
 
26
27
  const payload = this.payload as KaspaSignTransactionParams;
27
28