@onekeyfe/hd-core 1.2.2-alpha.12 → 1.2.2-alpha.120

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 (67) hide show
  1. package/README.md +1 -1
  2. package/__tests__/AllNetworkGetAddressBase.tracing.test.ts +452 -9
  3. package/__tests__/DeviceCommands.test.ts +254 -1
  4. package/__tests__/core-error-output.test.ts +92 -1
  5. package/__tests__/device-lifecycle-events.test.ts +379 -15
  6. package/__tests__/open-wallet-session-error-response.test.ts +2 -2
  7. package/__tests__/open-wallet-session.test.ts +8 -411
  8. package/__tests__/protocol-v2.test.ts +86 -0
  9. package/__tests__/public-device-state-api.test.ts +2 -7
  10. package/__tests__/sol-sign-offchain-message.test.ts +64 -0
  11. package/dist/api/GetFeatures.d.ts.map +1 -1
  12. package/dist/api/GetPassphraseState.d.ts.map +1 -1
  13. package/dist/api/OpenWalletSession.d.ts.map +1 -1
  14. package/dist/api/UploadPortfolio.d.ts +1 -0
  15. package/dist/api/UploadPortfolio.d.ts.map +1 -1
  16. package/dist/api/allnetwork/AllNetworkGetAddress.d.ts.map +1 -1
  17. package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts +6 -0
  18. package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
  19. package/dist/api/allnetwork/AllNetworkGetAddressByLoop.d.ts.map +1 -1
  20. package/dist/api/device/DeviceVerify.d.ts.map +1 -1
  21. package/dist/api/solana/SolSignOffchainMessage.d.ts.map +1 -1
  22. package/dist/core/RequestQueue.d.ts +1 -0
  23. package/dist/core/RequestQueue.d.ts.map +1 -1
  24. package/dist/core/index.d.ts +3 -1
  25. package/dist/core/index.d.ts.map +1 -1
  26. package/dist/core/uiPromiseRegistry.d.ts +1 -1
  27. package/dist/device/Device.d.ts +2 -0
  28. package/dist/device/Device.d.ts.map +1 -1
  29. package/dist/device/DeviceCommands.d.ts +5 -4
  30. package/dist/device/DeviceCommands.d.ts.map +1 -1
  31. package/dist/index.d.ts +35 -30
  32. package/dist/index.js +402 -208
  33. package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
  34. package/dist/types/api/getFeatures.d.ts.map +1 -1
  35. package/dist/types/api/getPassphraseState.d.ts.map +1 -1
  36. package/dist/types/api/openWalletSession.d.ts +1 -10
  37. package/dist/types/api/openWalletSession.d.ts.map +1 -1
  38. package/dist/types/api/protocolV2.d.ts +3 -4
  39. package/dist/types/api/protocolV2.d.ts.map +1 -1
  40. package/dist/types/api/solSignOffchainMessage.d.ts +1 -0
  41. package/dist/types/api/solSignOffchainMessage.d.ts.map +1 -1
  42. package/dist/types/params.d.ts.map +1 -1
  43. package/dist/utils/patch.d.ts +1 -1
  44. package/dist/utils/patch.d.ts.map +1 -1
  45. package/package.json +4 -4
  46. package/src/api/GetFeatures.ts +1 -0
  47. package/src/api/GetPassphraseState.ts +1 -0
  48. package/src/api/OpenWalletSession.ts +7 -77
  49. package/src/api/UploadPortfolio.ts +5 -4
  50. package/src/api/allnetwork/AllNetworkGetAddress.ts +47 -20
  51. package/src/api/allnetwork/AllNetworkGetAddressBase.ts +88 -22
  52. package/src/api/allnetwork/AllNetworkGetAddressByLoop.ts +3 -0
  53. package/src/api/device/DeviceVerify.ts +8 -0
  54. package/src/api/solana/SolSignOffchainMessage.ts +44 -4
  55. package/src/core/RequestQueue.ts +20 -0
  56. package/src/core/index.ts +116 -49
  57. package/src/data/messages/messages-protocol-v2.json +49 -33
  58. package/src/data/messages/messages.json +8 -5
  59. package/src/device/Device.ts +51 -27
  60. package/src/device/DeviceCommands.ts +29 -2
  61. package/src/protocols/protocol-v2/walletSession.ts +7 -0
  62. package/src/types/api/getFeatures.ts +2 -1
  63. package/src/types/api/getPassphraseState.ts +2 -5
  64. package/src/types/api/openWalletSession.ts +7 -19
  65. package/src/types/api/protocolV2.ts +3 -4
  66. package/src/types/api/solSignOffchainMessage.ts +2 -0
  67. package/src/types/params.ts +7 -0
package/dist/index.js CHANGED
@@ -291,7 +291,6 @@ const writeFirmwareByteSource = ({ source, chunkSize, write, }) => __awaiter(voi
291
291
  const OpenWalletSessionMode = {
292
292
  Standard: 'standard',
293
293
  SelectHidden: 'select-hidden',
294
- ResumeHidden: 'resume-hidden',
295
294
  };
296
295
 
297
296
  exports.EOneKeyDeviceMode = void 0;
@@ -13203,7 +13202,8 @@ var nested$2 = {
13203
13202
  },
13204
13203
  SolanaOffChainMessageVersion: {
13205
13204
  values: {
13206
- MESSAGE_VERSION_0: 0
13205
+ MESSAGE_VERSION_0: 0,
13206
+ MESSAGE_VERSION_1: 1
13207
13207
  }
13208
13208
  },
13209
13209
  SolanaOffChainMessageFormat: {
@@ -13236,14 +13236,16 @@ var nested$2 = {
13236
13236
  },
13237
13237
  message_format: {
13238
13238
  type: "SolanaOffChainMessageFormat",
13239
- id: 4,
13240
- options: {
13241
- "default": "V0_RESTRICTED_ASCII"
13242
- }
13239
+ id: 4
13243
13240
  },
13244
13241
  application_domain: {
13245
13242
  type: "bytes",
13246
13243
  id: 5
13244
+ },
13245
+ required_signers: {
13246
+ rule: "repeated",
13247
+ type: "bytes",
13248
+ id: 7
13247
13249
  }
13248
13250
  }
13249
13251
  },
@@ -31499,10 +31501,6 @@ var nested = {
31499
31501
  request_id: {
31500
31502
  type: "bytes",
31501
31503
  id: 5
31502
- },
31503
- source_fingerprint: {
31504
- type: "uint32",
31505
- id: 6
31506
31504
  }
31507
31505
  }
31508
31506
  },
@@ -31758,10 +31756,6 @@ var nested = {
31758
31756
  expected_address: {
31759
31757
  type: "bytes",
31760
31758
  id: 12
31761
- },
31762
- source_fingerprint: {
31763
- type: "uint32",
31764
- id: 13
31765
31759
  }
31766
31760
  }
31767
31761
  },
@@ -31846,10 +31840,6 @@ var nested = {
31846
31840
  expected_address: {
31847
31841
  type: "bytes",
31848
31842
  id: 12
31849
- },
31850
- source_fingerprint: {
31851
- type: "uint32",
31852
- id: 13
31853
31843
  }
31854
31844
  }
31855
31845
  },
@@ -31997,7 +31987,29 @@ var nested = {
31997
31987
  type: "EthereumAuthorizationSignature",
31998
31988
  id: 10
31999
31989
  }
32000
- }
31990
+ },
31991
+ reserved: [
31992
+ [
31993
+ 5,
31994
+ 5
31995
+ ],
31996
+ [
31997
+ 6,
31998
+ 6
31999
+ ],
32000
+ [
32001
+ 7,
32002
+ 7
32003
+ ],
32004
+ [
32005
+ 8,
32006
+ 8
32007
+ ],
32008
+ [
32009
+ 9,
32010
+ 9
32011
+ ]
32012
+ ]
32001
32013
  },
32002
32014
  EthereumTxAckOneKey: {
32003
32015
  fields: {
@@ -32026,10 +32038,6 @@ var nested = {
32026
32038
  chain_id: {
32027
32039
  type: "uint64",
32028
32040
  id: 3
32029
- },
32030
- source_fingerprint: {
32031
- type: "uint32",
32032
- id: 4
32033
32041
  }
32034
32042
  }
32035
32043
  },
@@ -36027,7 +36035,8 @@ var nested = {
36027
36035
  },
36028
36036
  SolanaOffChainMessageVersion: {
36029
36037
  values: {
36030
- MESSAGE_VERSION_0: 0
36038
+ MESSAGE_VERSION_0: 0,
36039
+ MESSAGE_VERSION_1: 1
36031
36040
  }
36032
36041
  },
36033
36042
  SolanaOffChainMessageFormat: {
@@ -36075,10 +36084,6 @@ var nested = {
36075
36084
  rule: "required",
36076
36085
  type: "bytes",
36077
36086
  id: 2
36078
- },
36079
- source_fingerprint: {
36080
- type: "uint32",
36081
- id: 3
36082
36087
  }
36083
36088
  }
36084
36089
  },
@@ -36115,17 +36120,15 @@ var nested = {
36115
36120
  },
36116
36121
  message_format: {
36117
36122
  type: "SolanaOffChainMessageFormat",
36118
- id: 4,
36119
- options: {
36120
- "default": "V0_RESTRICTED_ASCII"
36121
- }
36123
+ id: 4
36122
36124
  },
36123
36125
  application_domain: {
36124
36126
  type: "bytes",
36125
36127
  id: 5
36126
36128
  },
36127
- source_fingerprint: {
36128
- type: "uint32",
36129
+ required_signers: {
36130
+ rule: "repeated",
36131
+ type: "bytes",
36129
36132
  id: 6
36130
36133
  }
36131
36134
  }
@@ -36144,10 +36147,6 @@ var nested = {
36144
36147
  rule: "required",
36145
36148
  type: "bytes",
36146
36149
  id: 2
36147
- },
36148
- source_fingerprint: {
36149
- type: "uint32",
36150
- id: 3
36151
36150
  }
36152
36151
  }
36153
36152
  },
@@ -38564,6 +38563,7 @@ var nested = {
38564
38563
  MessageType_DeviceFindMyTokenState: 60450,
38565
38564
  MessageType_DeviceFindMyTokenUpdate: 60451,
38566
38565
  MessageType_DeviceFindMyTokenStateGet: 60452,
38566
+ MessageType_DeviceAnimationControl: 60461,
38567
38567
  MessageType_DeviceInfoGet: 60600,
38568
38568
  MessageType_DeviceInfo: 60601,
38569
38569
  MessageType_DeviceStatusGet: 60602,
@@ -38902,6 +38902,26 @@ var nested = {
38902
38902
  }
38903
38903
  }
38904
38904
  },
38905
+ DeviceAnimationAction: {
38906
+ values: {
38907
+ AnimationAction_Unknown: 0,
38908
+ AnimationAction_Start: 1,
38909
+ AnimationAction_Stop: 2
38910
+ }
38911
+ },
38912
+ DeviceAnimationControl: {
38913
+ fields: {
38914
+ action: {
38915
+ rule: "required",
38916
+ type: "DeviceAnimationAction",
38917
+ id: 1
38918
+ },
38919
+ timeout_ms: {
38920
+ type: "uint32",
38921
+ id: 2
38922
+ }
38923
+ }
38924
+ },
38905
38925
  DeviceFactoryAck: {
38906
38926
  values: {
38907
38927
  FACTORY_ACK_SUCCESS: 0,
@@ -38963,6 +38983,10 @@ var nested = {
38963
38983
  manufacture_time: {
38964
38984
  type: "DeviceFactoryInfoManufactureTime",
38965
38985
  id: 5
38986
+ },
38987
+ data: {
38988
+ type: "bytes",
38989
+ id: 100
38966
38990
  }
38967
38991
  }
38968
38992
  },
@@ -38972,11 +38996,19 @@ var nested = {
38972
38996
  rule: "required",
38973
38997
  type: "DeviceFactoryInfo",
38974
38998
  id: 1
38999
+ },
39000
+ full_data: {
39001
+ type: "bool",
39002
+ id: 2
38975
39003
  }
38976
39004
  }
38977
39005
  },
38978
39006
  DeviceFactoryInfoGet: {
38979
39007
  fields: {
39008
+ full_data: {
39009
+ type: "bool",
39010
+ id: 1
39011
+ }
38980
39012
  }
38981
39013
  },
38982
39014
  DeviceFactoryPermanentLock: {
@@ -41846,6 +41878,7 @@ function getProtocolV2WalletSession(device, options) {
41846
41878
  ? device.getInternalState()
41847
41879
  : undefined;
41848
41880
  let response;
41881
+ let walletSelectionRequested = false;
41849
41882
  let resumed = false;
41850
41883
  let walletStatusRefreshed = false;
41851
41884
  const markWalletStatusRefreshed = () => {
@@ -42017,6 +42050,7 @@ function getProtocolV2WalletSession(device, options) {
42017
42050
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.WalletSessionInvalid);
42018
42051
  }
42019
42052
  yield lockAttachPinBeforePassphraseSelection();
42053
+ walletSelectionRequested = true;
42020
42054
  response = yield selectDeviceSession(device, expectedPassphraseState, options === null || options === void 0 ? void 0 : options.deriveCardano, markWalletStatusRefreshed);
42021
42055
  }
42022
42056
  let { message } = response;
@@ -42039,6 +42073,10 @@ function getProtocolV2WalletSession(device, options) {
42039
42073
  device.clearInternalState();
42040
42074
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.WalletSessionInvalid);
42041
42075
  }
42076
+ if (walletSelectionRequested) {
42077
+ clearCurrentWalletSession();
42078
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceCheckPassphraseStateError);
42079
+ }
42042
42080
  if (options === null || options === void 0 ? void 0 : options.onlyMainPin) {
42043
42081
  (_j = device.clearStandardInternalState) === null || _j === void 0 ? void 0 : _j.call(device);
42044
42082
  yield selectStandardWallet(true);
@@ -43900,6 +43938,7 @@ class DeviceCommands {
43900
43938
  var _a, _b;
43901
43939
  return __awaiter(this, void 0, void 0, function* () {
43902
43940
  this.disposed = true;
43941
+ this.disposalToken = {};
43903
43942
  yield ((_b = (_a = this.transport).cancel) === null || _b === void 0 ? void 0 : _b.call(_a));
43904
43943
  });
43905
43944
  }
@@ -44073,7 +44112,24 @@ class DeviceCommands {
44073
44112
  }
44074
44113
  _commonCall(type, msg, options) {
44075
44114
  return __awaiter(this, void 0, void 0, function* () {
44076
- const resp = yield this.call(type, msg, options);
44115
+ const { disposalToken } = this;
44116
+ let resp = yield this.call(type, msg, options);
44117
+ for (let retry = 0; retry < 3 &&
44118
+ this.device.isProtocolV2() &&
44119
+ DEVICE_SESSION_CALLS.has(type) &&
44120
+ resp.type === 'Failure' &&
44121
+ resp.message.code === 'Failure_ProcessError' &&
44122
+ resp.message.subcode === hdTransport.DeviceSessionErrorCode.DeviceSessionError_Busy; retry += 1) {
44123
+ yield wait(100);
44124
+ if (this.device.wasInterruptedByUser()) {
44125
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceInterruptedFromUser);
44126
+ }
44127
+ this.checkDisposed();
44128
+ if (this.disposalToken !== disposalToken) {
44129
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'DeviceCommands lifecycle changed');
44130
+ }
44131
+ resp = yield this.call(type, msg, options);
44132
+ }
44077
44133
  return this._filterCommonTypes(resp, type, options);
44078
44134
  });
44079
44135
  }
@@ -46294,6 +46350,10 @@ class Device extends events.exports {
46294
46350
  }
46295
46351
  this.invalidateProtocolV2RuntimeState();
46296
46352
  }
46353
+ waitForRunCleanup() {
46354
+ var _a;
46355
+ return (_a = this.runCleanupPromise) !== null && _a !== void 0 ? _a : Promise.resolve();
46356
+ }
46297
46357
  run(fn, options) {
46298
46358
  return __awaiter(this, void 0, void 0, function* () {
46299
46359
  if (this.runPromise) {
@@ -46411,44 +46471,67 @@ class Device extends events.exports {
46411
46471
  });
46412
46472
  }
46413
46473
  interruptionFromUser() {
46414
- var _a, _b, _c, _d;
46415
- return __awaiter(this, void 0, void 0, function* () {
46416
- const error = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceInterruptedFromUser);
46417
- this.interruptedAttempt = this.connectionAttempt;
46418
- const cleanupPromise = this.runCleanupPromise;
46419
- const { cancelableAction } = this;
46420
- if (cancelableAction) {
46421
- yield cancelableAction(error);
46422
- }
46423
- else if (this.shouldSendFallbackProtocolCancel()) {
46424
- yield ((_b = (_a = this.commands) === null || _a === void 0 ? void 0 : _a.cancelDevice) === null || _b === void 0 ? void 0 : _b.call(_a).catch(cancelError => {
46425
- Log$h.debug('Protocol V2 fallback cancel error', cancelError);
46426
- }));
46474
+ var _a;
46475
+ const attempt = this.connectionAttempt;
46476
+ if (((_a = this.userInterruption) === null || _a === void 0 ? void 0 : _a.attempt) === attempt) {
46477
+ return this.userInterruption.promise;
46478
+ }
46479
+ const error = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceInterruptedFromUser);
46480
+ this.interruptedAttempt = attempt;
46481
+ const cleanupPromise = this.runCleanupPromise;
46482
+ const { cancelableAction, commands, runPromise, deviceConnector, mainId } = this;
46483
+ const sendFallbackCancel = this.shouldSendFallbackProtocolCancel();
46484
+ const acquired = this.hasDeviceAcquire();
46485
+ const promise = (() => __awaiter(this, void 0, void 0, function* () {
46486
+ var _b;
46487
+ try {
46488
+ if (cancelableAction) {
46489
+ yield cancelableAction(error);
46490
+ }
46491
+ else if (sendFallbackCancel) {
46492
+ yield ((_b = commands === null || commands === void 0 ? void 0 : commands.cancelDevice) === null || _b === void 0 ? void 0 : _b.call(commands).catch(cancelError => {
46493
+ Log$h.debug('Protocol V2 fallback cancel error', cancelError);
46494
+ }));
46495
+ }
46496
+ else if (!acquired) {
46497
+ if (mainId && (deviceConnector === null || deviceConnector === void 0 ? void 0 : deviceConnector.disconnect)) {
46498
+ yield deviceConnector.disconnect(mainId);
46499
+ }
46500
+ if (this.connectionAttempt === attempt)
46501
+ this.markTransportDisconnected();
46502
+ }
46503
+ yield (commands === null || commands === void 0 ? void 0 : commands.cancel());
46427
46504
  }
46428
- else if (!this.hasDeviceAcquire()) {
46429
- if (this.mainId && ((_c = this.deviceConnector) === null || _c === void 0 ? void 0 : _c.disconnect)) {
46430
- yield this.deviceConnector.disconnect(this.mainId).catch(disconnectError => {
46431
- Log$h.debug('Ignored disconnect during user cancel without acquire', disconnectError);
46505
+ catch (cleanupError) {
46506
+ Log$h.warn('User cancellation cleanup failed; disconnecting device', cleanupError);
46507
+ if (mainId && (deviceConnector === null || deviceConnector === void 0 ? void 0 : deviceConnector.disconnect)) {
46508
+ yield deviceConnector.disconnect(mainId).catch(disconnectError => {
46509
+ Log$h.debug('User cancellation fallback disconnect failed', disconnectError);
46432
46510
  });
46433
46511
  }
46434
- this.markTransportDisconnected();
46512
+ if (this.connectionAttempt === attempt)
46513
+ this.markTransportDisconnected();
46435
46514
  }
46436
- yield ((_d = this.commands) === null || _d === void 0 ? void 0 : _d.cancel());
46437
- if (this.runPromise) {
46438
- this.runPromise.reject(error);
46439
- this.runPromise = null;
46515
+ finally {
46516
+ runPromise === null || runPromise === void 0 ? void 0 : runPromise.reject(error);
46517
+ if (this.runPromise === runPromise)
46518
+ this.runPromise = null;
46519
+ yield (cleanupPromise === null || cleanupPromise === void 0 ? void 0 : cleanupPromise.catch(() => undefined));
46440
46520
  }
46441
- yield (cleanupPromise === null || cleanupPromise === void 0 ? void 0 : cleanupPromise.catch(() => undefined));
46442
- });
46521
+ }))();
46522
+ this.userInterruption = { attempt, promise };
46523
+ return promise;
46443
46524
  }
46444
46525
  setCancelableAction(callback) {
46445
- this.cancelableAction = (e) => callback(e)
46526
+ const action = (e) => callback(e)
46446
46527
  .catch(e2 => {
46447
46528
  Log$h.debug('cancelableAction error', e2);
46448
46529
  })
46449
46530
  .finally(() => {
46450
- this.clearCancelableAction();
46531
+ if (this.cancelableAction === action)
46532
+ this.clearCancelableAction();
46451
46533
  });
46534
+ this.cancelableAction = action;
46452
46535
  }
46453
46536
  clearCancelableAction() {
46454
46537
  this.cancelableAction = undefined;
@@ -47558,15 +47641,6 @@ function validateResult(result, nonNullableFields, options) {
47558
47641
  }
47559
47642
  }
47560
47643
 
47561
- const requiredString = (value, name) => {
47562
- if (value === undefined || value === null) {
47563
- throw invalidParameter(`Missing required parameter: ${name}`);
47564
- }
47565
- if (typeof value !== 'string' || !value.trim()) {
47566
- throw invalidParameter(`Parameter [${name}] must be a non-empty string.`);
47567
- }
47568
- return value.trim();
47569
- };
47570
47644
  const wasResumed = (session) => !!session &&
47571
47645
  typeof session === 'object' &&
47572
47646
  'resumed' in session &&
@@ -47588,25 +47662,16 @@ const normalizeParams = (payload) => {
47588
47662
  throw invalidParameter('Parameter [mode] is required.');
47589
47663
  }
47590
47664
  if (payload.mode !== OpenWalletSessionMode.Standard &&
47591
- payload.mode !== OpenWalletSessionMode.SelectHidden &&
47592
- payload.mode !== OpenWalletSessionMode.ResumeHidden) {
47593
- throw invalidParameter('Parameter [mode] must be one of standard, select-hidden, or resume-hidden.');
47665
+ payload.mode !== OpenWalletSessionMode.SelectHidden) {
47666
+ throw invalidParameter('Parameter [mode] must be one of standard or select-hidden.');
47594
47667
  }
47595
47668
  if (payload.useEmptyPassphrase !== undefined || payload.initSession !== undefined) {
47596
47669
  throw invalidParameter('Legacy parameters [useEmptyPassphrase] and [initSession] are not supported by openWalletSession.');
47597
47670
  }
47598
- if (payload.mode === OpenWalletSessionMode.Standard ||
47599
- payload.mode === OpenWalletSessionMode.SelectHidden) {
47600
- if (payload.deviceId !== undefined || payload.passphraseState !== undefined) {
47601
- throw invalidParameter('Parameters [deviceId] and [passphraseState] are only allowed with mode [resume-hidden].');
47602
- }
47603
- return { mode: payload.mode };
47671
+ if (payload.deviceId !== undefined || payload.passphraseState !== undefined) {
47672
+ throw invalidParameter('Parameters [deviceId] and [passphraseState] are not supported by openWalletSession. Pass passphraseState on later address and signing calls.');
47604
47673
  }
47605
- return {
47606
- mode: OpenWalletSessionMode.ResumeHidden,
47607
- deviceId: requiredString(payload.deviceId, 'deviceId'),
47608
- passphraseState: requiredString(payload.passphraseState, 'passphraseState'),
47609
- };
47674
+ return { mode: payload.mode };
47610
47675
  };
47611
47676
  class OpenWalletSession extends BaseMethod {
47612
47677
  getSupportedProtocols() {
@@ -47709,43 +47774,6 @@ class OpenWalletSession extends BaseMethod {
47709
47774
  resumed: wasResumed(session),
47710
47775
  };
47711
47776
  }
47712
- if (this.params.mode === OpenWalletSessionMode.ResumeHidden) {
47713
- if (isProtocolV2) {
47714
- yield ensureProtocolV2WalletStatus();
47715
- const refreshedDeviceId = requireDeviceId();
47716
- if (refreshedDeviceId !== this.params.deviceId) {
47717
- deviceWalletSessionStore.delete(this.params.deviceId, this.params.passphraseState);
47718
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceCheckDeviceIdError);
47719
- }
47720
- }
47721
- else if (requireDeviceId() !== this.params.deviceId) {
47722
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceCheckDeviceIdError);
47723
- }
47724
- this.device.passphraseState = this.params.passphraseState;
47725
- const cachedSessionId = deviceWalletSessionStore.get(this.params.deviceId, this.params.passphraseState);
47726
- if (!cachedSessionId && !isProtocolV2) {
47727
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.WalletSessionInvalid);
47728
- }
47729
- if (!isProtocolV2) {
47730
- yield this.device.initialize({
47731
- deviceId: this.params.deviceId,
47732
- passphraseState: this.params.passphraseState,
47733
- });
47734
- }
47735
- const session = isProtocolV2
47736
- ? yield getProtocolV2WalletSession(this.device, {
47737
- expectedPassphraseState: this.params.passphraseState,
47738
- })
47739
- : yield getPassphraseStateWithRefreshDeviceInfo(this.device, {
47740
- expectPassphraseState: this.params.passphraseState,
47741
- });
47742
- const deviceId = requireDeviceId();
47743
- if (session.passphraseState !== this.params.passphraseState) {
47744
- this.device.clearInternalState();
47745
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceCheckPassphraseStateError);
47746
- }
47747
- return Object.assign(Object.assign({ protocol, walletType: 'hidden', deviceId }, requireHiddenWalletResponse(session)), { resumed: wasResumed(session) || (!isProtocolV2 && session.newSession === cachedSessionId) });
47748
- }
47749
47777
  this.device.passphraseState = undefined;
47750
47778
  const walletStatus = yield ensureProtocolV2WalletStatus();
47751
47779
  if (isProtocolV2 && walletStatus.status.passphraseProtection !== true) {
@@ -49156,6 +49184,14 @@ class DeviceVerify extends BaseMethod {
49156
49184
  this.unlockPolicy = 'unlock-before-run';
49157
49185
  this.protocolV2PreUnlockPinType = hdTransport.DeviceSessionPinType.Any;
49158
49186
  this.useDevicePassphraseState = false;
49187
+ this.protocolV2UiInteraction = {
49188
+ request: 'button',
49189
+ source: 'method-lifecycle',
49190
+ reason: 'device-management',
49191
+ completion: 'operation-completed',
49192
+ deviceOnly: true,
49193
+ operation: 'deviceVerify',
49194
+ };
49159
49195
  validateParams(this.payload, [{ name: 'dataHex', type: 'hexString' }]);
49160
49196
  this.params = {
49161
49197
  data: formatAnyHex(this.payload.dataHex),
@@ -55408,16 +55444,16 @@ const FILESYSTEM_FILE_WRITE_MESSAGE_TYPE = 60805;
55408
55444
  const PORTFOLIO_UPDATE_MESSAGE_TYPE = 61400;
55409
55445
  class UploadPortfolio extends FileWrite {
55410
55446
  init() {
55411
- const { packageBase64, timeoutMs } = this.payload;
55447
+ const { packageBase64, timeoutMs, uiMode = 'silent' } = this.payload;
55412
55448
  const packageBytes = decodeCanonicalBase64({
55413
55449
  value: packageBase64,
55414
55450
  parameterName: 'packageBase64',
55415
55451
  maxBytes: PORTFOLIO_PACKAGE_MAX_BYTES,
55416
55452
  });
55417
- this.payload = Object.assign(Object.assign({}, this.payload), { path: PORTFOLIO_PENDING_PATH, offset: 0, data: packageBytes, chunkSize: PORTFOLIO_CHUNK_SIZE, overwrite: true, append: false, emitProgress: false, timeoutMs });
55453
+ this.payload = Object.assign(Object.assign({}, this.payload), { path: PORTFOLIO_PENDING_PATH, offset: 0, data: packageBytes, chunkSize: PORTFOLIO_CHUNK_SIZE, overwrite: true, append: false, emitProgress: uiMode === 'progress', timeoutMs });
55418
55454
  super.init();
55419
55455
  this.unlockPolicy = 'none';
55420
- this.protocolV2UiMode = 'none';
55456
+ this.protocolV2UiMode = uiMode === 'progress' ? 'auto' : 'none';
55421
55457
  }
55422
55458
  run() {
55423
55459
  const _super = Object.create(null, {
@@ -55878,6 +55914,8 @@ class AllNetworkGetAddressBase extends BaseMethod {
55878
55914
  constructor() {
55879
55915
  super(...arguments);
55880
55916
  this.abortController = null;
55917
+ this.loadingCleanupInBackground = false;
55918
+ this.protocolV2ResumedSeedDomains = new Set();
55881
55919
  }
55882
55920
  getSupportedProtocols() {
55883
55921
  return ['V1', 'V2'];
@@ -55913,6 +55951,19 @@ class AllNetworkGetAddressBase extends BaseMethod {
55913
55951
  _originalIndex: originalIndex,
55914
55952
  };
55915
55953
  }
55954
+ hasProtocolV2WalletResume(deriveCardano) {
55955
+ if (deriveCardano) {
55956
+ return this.protocolV2ResumedSeedDomains.has('cardano');
55957
+ }
55958
+ return (this.protocolV2ResumedSeedDomains.has('standard') ||
55959
+ this.protocolV2ResumedSeedDomains.has('cardano'));
55960
+ }
55961
+ markProtocolV2WalletResumed(deriveCardano) {
55962
+ this.protocolV2ResumedSeedDomains.add('standard');
55963
+ if (deriveCardano) {
55964
+ this.protocolV2ResumedSeedDomains.add('cardano');
55965
+ }
55966
+ }
55916
55967
  callMethod(methodName, params, rootFingerprint) {
55917
55968
  var _a, _b, _c;
55918
55969
  return __awaiter(this, void 0, void 0, function* () {
@@ -55975,11 +56026,14 @@ class AllNetworkGetAddressBase extends BaseMethod {
55975
56026
  const useEmptyPassphrase = this.payload.useEmptyPassphrase === true;
55976
56027
  const deriveCardano = method.name.startsWith('cardano') ? true : undefined;
55977
56028
  const shouldResumeWalletSession = useEmptyPassphrase || !!this.payload.passphraseState;
55978
- if (this.device.isProtocolV2() && shouldResumeWalletSession) {
56029
+ if (this.device.isProtocolV2() &&
56030
+ shouldResumeWalletSession &&
56031
+ !this.hasProtocolV2WalletResume(deriveCardano)) {
55979
56032
  const passphraseStateSafety = yield this.device.checkPassphraseStateSafety(this.payload.passphraseState, useEmptyPassphrase, this.payload.skipPassphraseCheck, deriveCardano, (_d = this.protocolV2UnlockContext) === null || _d === void 0 ? void 0 : _d.preflightMainPinSelected);
55980
56033
  if (!passphraseStateSafety) {
55981
56034
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceCheckPassphraseStateError);
55982
56035
  }
56036
+ this.markProtocolV2WalletResumed(deriveCardano);
55983
56037
  }
55984
56038
  }),
55985
56039
  });
@@ -56015,27 +56069,61 @@ class AllNetworkGetAddressBase extends BaseMethod {
56015
56069
  return result;
56016
56070
  });
56017
56071
  }
56018
- run() {
56072
+ stopAllNetworkLoading(canSend = true) {
56019
56073
  return __awaiter(this, void 0, void 0, function* () {
56020
- const res = yield this.device.commands.typedCall('GetPublicKey', 'PublicKey', {
56021
- address_n: [toHardened(44), toHardened(1), toHardened(0)],
56022
- coin_name: 'Testnet',
56023
- script_type: 'SPENDADDRESS',
56024
- show_display: false,
56025
- });
56026
- if (!this.device.isProtocolV2()) {
56027
- this.postMessage(createUiMessage(UI_REQUEST.CLOSE_UI_PIN_WINDOW));
56074
+ const commands = this.loadingCommands;
56075
+ this.loadingCommands = undefined;
56076
+ if (!canSend || !commands || commands.disposed || commands !== this.device.commands)
56077
+ return;
56078
+ try {
56079
+ yield commands.typedCall('DeviceAnimationControl', 'Success', {
56080
+ action: hdTransport.Messages.DeviceAnimationAction.AnimationAction_Stop,
56081
+ });
56028
56082
  }
56029
- if (res.message.root_fingerprint == null) {
56030
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallMethodInvalidParameter);
56083
+ catch (_a) {
56084
+ }
56085
+ });
56086
+ }
56087
+ run() {
56088
+ return __awaiter(this, void 0, void 0, function* () {
56089
+ this.loadingCleanupInBackground = false;
56090
+ try {
56091
+ if (this.device.isProtocolV2() && this.device.getCurrentDeviceType() === hdShared.EDeviceType.Pro2) {
56092
+ const protocolInfo = yield this.device.ensureProtocolV2RuntimeContext();
56093
+ if (supportsProtocolV2Message(protocolInfo, 60461)) {
56094
+ const { commands } = this.device;
56095
+ yield commands.typedCall('DeviceAnimationControl', 'Success', {
56096
+ action: hdTransport.Messages.DeviceAnimationAction.AnimationAction_Start,
56097
+ });
56098
+ this.loadingCommands = commands;
56099
+ }
56100
+ }
56101
+ const res = yield this.device.commands.typedCall('GetPublicKey', 'PublicKey', {
56102
+ address_n: [toHardened(44), toHardened(1), toHardened(0)],
56103
+ coin_name: 'Testnet',
56104
+ script_type: 'SPENDADDRESS',
56105
+ show_display: false,
56106
+ });
56107
+ if (!this.device.isProtocolV2()) {
56108
+ this.postMessage(createUiMessage(UI_REQUEST.CLOSE_UI_PIN_WINDOW));
56109
+ }
56110
+ if (res.message.root_fingerprint == null) {
56111
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallMethodInvalidParameter);
56112
+ }
56113
+ this.abortController = new AbortController();
56114
+ return yield this.getAllNetworkAddress(res.message.root_fingerprint);
56031
56115
  }
56032
- this.abortController = new AbortController();
56033
- return this.getAllNetworkAddress(res.message.root_fingerprint).catch(e => {
56116
+ catch (e) {
56117
+ yield this.stopAllNetworkLoading(false);
56034
56118
  if (e instanceof hdShared.HardwareError && e.errorCode === hdShared.HardwareErrorCode.RepeatUnlocking) {
56035
56119
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RepeatUnlocking, e.message);
56036
56120
  }
56037
56121
  throw e;
56038
- });
56122
+ }
56123
+ finally {
56124
+ if (!this.loadingCleanupInBackground)
56125
+ yield this.stopAllNetworkLoading();
56126
+ }
56039
56127
  });
56040
56128
  }
56041
56129
  }
@@ -56097,7 +56185,7 @@ function handleSkippableHardwareError(e, device, method) {
56097
56185
 
56098
56186
  class AllNetworkGetAddress extends AllNetworkGetAddressBase {
56099
56187
  getAllNetworkAddress(rootFingerprint) {
56100
- var _a, _b, _c, _d;
56188
+ var _a, _b, _c;
56101
56189
  return __awaiter(this, void 0, void 0, function* () {
56102
56190
  const responses = [];
56103
56191
  const resultMap = {};
@@ -56107,40 +56195,53 @@ class AllNetworkGetAddress extends AllNetworkGetAddressBase {
56107
56195
  payload: param,
56108
56196
  originalIndex: index,
56109
56197
  }));
56110
- const groupedMethodParams = methodParams.reduce((groups, param) => {
56198
+ const methodGroups = methodParams.reduce((groups, param) => {
56111
56199
  var _a;
56112
56200
  const group = (_a = groups.get(param.methodName)) !== null && _a !== void 0 ? _a : [];
56113
56201
  group.push(param);
56114
56202
  groups.set(param.methodName, group);
56115
56203
  return groups;
56116
56204
  }, new Map());
56117
- const requiresProtocolV2WalletHandoff = this.device.isProtocolV2() &&
56118
- (this.payload.useEmptyPassphrase === true || !!this.payload.passphraseState);
56119
- const methodGroups = requiresProtocolV2WalletHandoff
56120
- ? methodParams.map(param => [param.methodName, [param]])
56121
- : Array.from(groupedMethodParams.entries());
56122
- let i = 0;
56123
- for (const [methodName, params] of methodGroups) {
56124
- const methodParams = {
56205
+ let processed = 0;
56206
+ for (const [methodName, params] of methodGroups.entries()) {
56207
+ const methodCallParams = {
56125
56208
  bundle: params.map(param => (Object.assign({}, param.params))),
56126
56209
  };
56127
56210
  if ((_a = this.abortController) === null || _a === void 0 ? void 0 : _a.signal.aborted) {
56128
56211
  throw new Error(hdShared.HardwareErrorCodeMessage[hdShared.HardwareErrorCode.RepeatUnlocking]);
56129
56212
  }
56130
- const response = yield this.callMethod(methodName, methodParams, rootFingerprint);
56131
- if ((_b = this.abortController) === null || _b === void 0 ? void 0 : _b.signal.aborted) {
56213
+ const isProtocolV2 = this.device.isProtocolV2();
56214
+ const runIndividually = isProtocolV2 &&
56215
+ params.length > 1 &&
56216
+ params.some(param => param._originRequestParams.showOnOneKey !== false);
56217
+ let response = [];
56218
+ if (!runIndividually) {
56219
+ response = yield this.callMethod(methodName, methodCallParams, rootFingerprint);
56220
+ }
56221
+ if (isProtocolV2 &&
56222
+ params.length > 1 &&
56223
+ (runIndividually || response.every(item => !item.success))) {
56224
+ response = [];
56225
+ for (const param of params) {
56226
+ if ((_b = this.abortController) === null || _b === void 0 ? void 0 : _b.signal.aborted) {
56227
+ throw new Error(hdShared.HardwareErrorCodeMessage[hdShared.HardwareErrorCode.RepeatUnlocking]);
56228
+ }
56229
+ const itemResponse = yield this.callMethod(methodName, { bundle: [Object.assign({}, param.params)] }, rootFingerprint);
56230
+ response.push(...itemResponse);
56231
+ }
56232
+ }
56233
+ if ((_c = this.abortController) === null || _c === void 0 ? void 0 : _c.signal.aborted) {
56132
56234
  throw new Error(hdShared.HardwareErrorCodeMessage[hdShared.HardwareErrorCode.RepeatUnlocking]);
56133
56235
  }
56134
- for (let i = 0; i < params.length; i++) {
56135
- const { _originRequestParams, _originalIndex } = params[i];
56136
- const responseKey = `${_originalIndex}`;
56137
- resultMap[responseKey] = Object.assign(Object.assign({}, _originRequestParams), response[i]);
56236
+ for (let index = 0; index < params.length; index++) {
56237
+ const { _originRequestParams, _originalIndex } = params[index];
56238
+ resultMap[`${_originalIndex}`] = Object.assign(Object.assign({}, _originRequestParams), response[index]);
56138
56239
  }
56139
- if (((_d = (_c = this.payload) === null || _c === void 0 ? void 0 : _c.bundle) === null || _d === void 0 ? void 0 : _d.length) > 1) {
56140
- const progress = Math.round(((i + 1) / this.payload.bundle.length) * 100);
56240
+ processed += params.length;
56241
+ if (bundle.length > 1) {
56242
+ const progress = Math.round((processed / bundle.length) * 100);
56141
56243
  this.postMessage(createUiMessage(UI_REQUEST.DEVICE_PROGRESS, { progress }));
56142
56244
  }
56143
- i++;
56144
56245
  }
56145
56246
  for (let i = 0; i < bundle.length; i++) {
56146
56247
  responses.push(resultMap[i]);
@@ -56162,6 +56263,7 @@ class AllNetworkGetAddressByLoop extends AllNetworkGetAddressBase {
56162
56263
  throw new Error('callbackIdFinish is required');
56163
56264
  }
56164
56265
  const bundle = this.payload.bundle || [this.payload];
56266
+ this.loadingCleanupInBackground = true;
56165
56267
  const callbackPromise = this.processCallbacksInBackground(bundle, rootFingerprint, callbackId, callbackIdFinish);
56166
56268
  this.device.pendingCallbackPromise = hdShared.createDeferred(callbackPromise);
56167
56269
  if (this.context && this.payload.connectId) {
@@ -56202,6 +56304,7 @@ class AllNetworkGetAddressByLoop extends AllNetworkGetAddressBase {
56202
56304
  });
56203
56305
  }
56204
56306
  catch (error) {
56307
+ yield this.stopAllNetworkLoading(false);
56205
56308
  let errorCode = error.errorCode || error.code;
56206
56309
  let errorMessage = error.message;
56207
56310
  if (error instanceof hdShared.HardwareError) {
@@ -56229,6 +56332,7 @@ class AllNetworkGetAddressByLoop extends AllNetworkGetAddressBase {
56229
56332
  });
56230
56333
  }
56231
56334
  finally {
56335
+ yield this.stopAllNetworkLoading();
56232
56336
  (_c = this.context) === null || _c === void 0 ? void 0 : _c.cancelCallbackTasks(this.payload.connectId);
56233
56337
  this.abortController = null;
56234
56338
  }
@@ -59463,6 +59567,23 @@ class SolSignTransaction extends BaseMethod {
59463
59567
  }
59464
59568
  }
59465
59569
 
59570
+ const SOLANA_PUBLIC_KEY_LENGTH = 32;
59571
+ const SOLANA_APPLICATION_DOMAIN_LENGTH = 32;
59572
+ const normalizeRequiredSigners = (requiredSigners = []) => {
59573
+ const normalized = requiredSigners.map((signer, index) => {
59574
+ if (typeof signer !== 'string' ||
59575
+ !isHexString(addHexPrefix(signer), SOLANA_PUBLIC_KEY_LENGTH)) {
59576
+ throw invalidParameter(`Parameter [requiredSigners][${index}] must be a ${SOLANA_PUBLIC_KEY_LENGTH}-byte hex public key.`);
59577
+ }
59578
+ return stripHexPrefix(signer).toLowerCase();
59579
+ });
59580
+ for (let index = 1; index < normalized.length; index += 1) {
59581
+ if (normalized[index - 1] >= normalized[index]) {
59582
+ throw invalidParameter('Parameter [requiredSigners] must be strictly sorted and unique.');
59583
+ }
59584
+ }
59585
+ return normalized;
59586
+ };
59466
59587
  class SolSignOffchainMessage extends BaseMethod {
59467
59588
  getSupportedProtocols() {
59468
59589
  return ['V1', 'V2'];
@@ -59477,15 +59598,21 @@ class SolSignOffchainMessage extends BaseMethod {
59477
59598
  { name: 'messageVersion', type: 'number', required: false },
59478
59599
  { name: 'messageFormat', type: 'number', required: false },
59479
59600
  { name: 'applicationDomainHex', type: 'hexString', required: false },
59601
+ { name: 'requiredSigners', type: 'array', required: false, allowEmpty: true },
59480
59602
  ]);
59481
- const { path, messageHex, messageVersion, messageFormat, applicationDomainHex } = this.payload;
59603
+ const { path, messageHex, messageVersion, messageFormat, applicationDomainHex, requiredSigners, } = this.payload;
59482
59604
  const addressN = validatePath(path, 3);
59605
+ if (applicationDomainHex !== undefined &&
59606
+ !isHexString(addHexPrefix(applicationDomainHex), SOLANA_APPLICATION_DOMAIN_LENGTH)) {
59607
+ throw invalidParameter('Parameter [applicationDomainHex] must be 32 bytes.');
59608
+ }
59483
59609
  this.params = {
59484
59610
  address_n: addressN,
59485
59611
  message: stripHexPrefix(messageHex),
59486
59612
  message_version: messageVersion !== null && messageVersion !== void 0 ? messageVersion : undefined,
59487
59613
  message_format: messageFormat !== null && messageFormat !== void 0 ? messageFormat : undefined,
59488
- application_domain: applicationDomainHex !== null && applicationDomainHex !== void 0 ? applicationDomainHex : undefined,
59614
+ application_domain: applicationDomainHex ? stripHexPrefix(applicationDomainHex) : undefined,
59615
+ required_signers: normalizeRequiredSigners(requiredSigners),
59489
59616
  };
59490
59617
  }
59491
59618
  getVersionRange() {
@@ -65531,6 +65658,29 @@ class RequestQueue {
65531
65658
  getTask(requestId) {
65532
65659
  return this.requestQueue.get(requestId);
65533
65660
  }
65661
+ waitForTask(task, pending) {
65662
+ return __awaiter(this, void 0, void 0, function* () {
65663
+ const signal = task.method.abortSignal;
65664
+ const cancellationError = () => hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallQueueActionCancelled);
65665
+ if (signal === null || signal === void 0 ? void 0 : signal.aborted)
65666
+ throw cancellationError();
65667
+ let onAbort;
65668
+ try {
65669
+ const cancelled = new Promise((_, reject) => {
65670
+ onAbort = () => reject(cancellationError());
65671
+ signal === null || signal === void 0 ? void 0 : signal.addEventListener('abort', onAbort, { once: true });
65672
+ });
65673
+ const result = yield Promise.race([pending(), cancelled]);
65674
+ if (signal === null || signal === void 0 ? void 0 : signal.aborted)
65675
+ throw cancellationError();
65676
+ return result;
65677
+ }
65678
+ finally {
65679
+ if (onAbort)
65680
+ signal === null || signal === void 0 ? void 0 : signal.removeEventListener('abort', onAbort);
65681
+ }
65682
+ });
65683
+ }
65534
65684
  getAbortController(requestId) {
65535
65685
  var _a;
65536
65686
  return (_a = this.requestQueue.get(requestId)) === null || _a === void 0 ? void 0 : _a.abortController;
@@ -65731,6 +65881,7 @@ const createUiProgressMessageFilter = (intervalMs = DEFAULT_UI_PROGRESS_INTERVAL
65731
65881
  const Log = getLogger(exports.LoggerNames.Core);
65732
65882
  const PRE_INITIALIZE_TTL_MS = 60 * 1000;
65733
65883
  const PRE_PENDING_CALL_TIMEOUT_MS = 15 * 1000;
65884
+ const PRO2_USB_SIGNING_COOLDOWN_MS = 1000;
65734
65885
  const preWarmInflight = new Map();
65735
65886
  const preWarmDoneAt = new Map();
65736
65887
  function resolveDeriveCardano(method) {
@@ -65897,33 +66048,37 @@ const waitForPendingPromise = (connectId, getPrePendingCallPromise, removePrePen
65897
66048
  if (pendingPromise) {
65898
66049
  Log.debug('pre pending call promise before call method, wait for it');
65899
66050
  let timer;
65900
- let timedOut = false;
65901
66051
  try {
65902
66052
  yield Promise.race([
65903
66053
  pendingPromise,
65904
- new Promise(resolve => {
66054
+ new Promise((_, reject) => {
65905
66055
  timer = setTimeout(() => {
65906
- timedOut = true;
65907
- resolve();
66056
+ reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceBusy, 'Previous device cancellation is still draining'));
65908
66057
  }, PRE_PENDING_CALL_TIMEOUT_MS);
65909
66058
  }),
65910
66059
  ]);
65911
- }
65912
- catch (error) {
66060
+ removePrePendingCallPromise === null || removePrePendingCallPromise === void 0 ? void 0 : removePrePendingCallPromise(connectId, pendingPromise);
65913
66061
  }
65914
66062
  finally {
65915
66063
  if (timer)
65916
66064
  clearTimeout(timer);
65917
- removePrePendingCallPromise === null || removePrePendingCallPromise === void 0 ? void 0 : removePrePendingCallPromise(connectId, pendingPromise);
65918
- }
65919
- if (timedOut) {
65920
- Log.warn('pre pending call promise timed out before call method', { connectId });
65921
66065
  }
65922
66066
  Log.debug('pre pending call promise before call method done');
65923
66067
  }
65924
66068
  });
66069
+ function getPostCallPendingPromise(method, device) {
66070
+ const cleanupPromise = device.waitForRunCleanup();
66071
+ const env = DataManager.getSettings('env');
66072
+ const deviceType = device.getCurrentDeviceType();
66073
+ const requiresSigningCooldown = method.name.includes('Sign') &&
66074
+ (deviceType === hdShared.EDeviceType.Pro2 || deviceType === hdShared.EDeviceType.Neo) &&
66075
+ (DataManager.isBrowserWebUsb(env) || DataManager.isDesktopWebUsb(env) || env === 'node-usb');
66076
+ return requiresSigningCooldown
66077
+ ? cleanupPromise.then(() => wait(PRO2_USB_SIGNING_COOLDOWN_MS)).then(() => undefined)
66078
+ : cleanupPromise;
66079
+ }
65925
66080
  const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, void 0, function* () {
65926
- var _d, _e, _f, _g, _h, _j, _k;
66081
+ var _d, _e, _f, _g, _h, _j;
65927
66082
  let messageResponse;
65928
66083
  const { requestQueue, getPrePendingCallPromise, removePrePendingCallPromise } = context;
65929
66084
  updateMethodRequestContext(method, { status: 'running' });
@@ -65937,21 +66092,27 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
65937
66092
  Log.debug('passphrase state change, clear device cache');
65938
66093
  DevicePool.clearDeviceCache(method.payload.connectId);
65939
66094
  }
65940
- if (method.connectId) {
65941
- yield context.waitForCallbackTasks(method.connectId);
65942
- }
65943
- yield waitForPendingPromise((_d = method.connectId) !== null && _d !== void 0 ? _d : '', getPrePendingCallPromise, removePrePendingCallPromise);
65944
66095
  const task = requestQueue.createTask(method);
65945
66096
  let preWarmCallbackTask;
65946
- if (method.isPreWarmSignal && method.connectId) {
65947
- preWarmCallbackTask = hdShared.createDeferred();
65948
- context.registerCallbackTask(method.connectId, preWarmCallbackTask);
65949
- }
65950
66097
  let device;
65951
66098
  try {
65952
- const connectId = (_e = method.connectId) !== null && _e !== void 0 ? _e : '';
66099
+ const connectId = (_d = method.connectId) !== null && _d !== void 0 ? _d : '';
66100
+ if (connectId) {
66101
+ yield requestQueue.waitForTask(task, () => context.waitForCallbackTasks(connectId));
66102
+ }
66103
+ yield requestQueue.waitForTask(task, () => {
66104
+ var _a;
66105
+ return waitForPendingPromise((_a = method.connectId) !== null && _a !== void 0 ? _a : '', getPrePendingCallPromise, removePrePendingCallPromise);
66106
+ });
66107
+ if (method.isPreWarmSignal && method.connectId) {
66108
+ preWarmCallbackTask = hdShared.createDeferred();
66109
+ context.registerCallbackTask(method.connectId, preWarmCallbackTask);
66110
+ }
65953
66111
  const pollingId = pollingManager.start(connectId);
65954
- device = yield ensureConnected(context, method, connectId, pollingId, (_f = task.abortController) === null || _f === void 0 ? void 0 : _f.signal);
66112
+ device = yield ensureConnected(context, method, connectId, pollingId, method.abortSignal);
66113
+ if ((_e = method.abortSignal) === null || _e === void 0 ? void 0 : _e.aborted) {
66114
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallQueueActionCancelled);
66115
+ }
65955
66116
  }
65956
66117
  catch (e) {
65957
66118
  preWarmCallbackTask === null || preWarmCallbackTask === void 0 ? void 0 : preWarmCallbackTask.resolve();
@@ -65966,7 +66127,7 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
65966
66127
  requestQueue.releaseTask(method.responseID);
65967
66128
  return createResponseMessage(method.responseID, false, { error: e });
65968
66129
  }
65969
- if ((_g = method.payload) === null || _g === void 0 ? void 0 : _g.onlyConnectBleDevice) {
66130
+ if ((_f = method.payload) === null || _f === void 0 ? void 0 : _f.onlyConnectBleDevice) {
65970
66131
  preWarmCallbackTask === null || preWarmCallbackTask === void 0 ? void 0 : preWarmCallbackTask.resolve();
65971
66132
  Log.debug('Call API - only connect ble device: ', device === null || device === void 0 ? void 0 : device.mainId);
65972
66133
  completeMethodRequestContext(method);
@@ -65974,11 +66135,11 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
65974
66135
  return createResponseMessage(method.responseID, true, null);
65975
66136
  }
65976
66137
  Log.debug('Call API - setDevice: ', device.mainId);
65977
- (_h = method.setDevice) === null || _h === void 0 ? void 0 : _h.call(method, device);
66138
+ (_g = method.setDevice) === null || _g === void 0 ? void 0 : _g.call(method, device);
65978
66139
  method.context = context;
65979
66140
  updateMethodRequestContext(method, {
65980
66141
  deviceInstanceId: device.instanceId,
65981
- commandsInstanceId: (_j = device.commands) === null || _j === void 0 ? void 0 : _j.instanceId,
66142
+ commandsInstanceId: (_h = device.commands) === null || _h === void 0 ? void 0 : _h.instanceId,
65982
66143
  });
65983
66144
  const activeRequests = getActiveRequestsByDeviceInstance(device.instanceId);
65984
66145
  if (activeRequests.length > 0) {
@@ -66004,17 +66165,21 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
66004
66165
  device.beginProtocolV2UiInteraction();
66005
66166
  device.on(DEVICE.SELECT_DEVICE_FOR_SWITCH_FIRMWARE_WEB_DEVICE, onSelectDeviceForSwitchFirmwareWebDeviceHandler);
66006
66167
  try {
66007
- if (method.connectId) {
66008
- yield context.waitForCallbackTasks(method.connectId, preWarmCallbackTask);
66168
+ const { connectId } = method;
66169
+ if (connectId) {
66170
+ yield requestQueue.waitForTask(task, () => context.waitForCallbackTasks(connectId, preWarmCallbackTask));
66009
66171
  }
66010
- yield waitForPendingPromise((_k = method.connectId) !== null && _k !== void 0 ? _k : '', getPrePendingCallPromise, removePrePendingCallPromise);
66172
+ yield requestQueue.waitForTask(task, () => {
66173
+ var _a;
66174
+ return waitForPendingPromise((_a = method.connectId) !== null && _a !== void 0 ? _a : '', getPrePendingCallPromise, removePrePendingCallPromise);
66175
+ });
66011
66176
  const inner = () => __awaiter(void 0, void 0, void 0, function* () {
66012
- var _l, _m;
66177
+ var _k, _l;
66013
66178
  method.assertProtocolSupported(device.getProtocol(), device.getCurrentFirmwareType());
66014
66179
  protocolV2Operation = device.isProtocolV2();
66015
66180
  const versionRange = device.getCurrentMethodVersionRange(type => method.getVersionRange()[type]);
66016
- const currentFirmwareVersion = (_l = device.getCurrentFirmwareVersionString()) !== null && _l !== void 0 ? _l : '0.0.0';
66017
- const currentBleVersion = (_m = device.getCurrentBLEFirmwareVersionString()) !== null && _m !== void 0 ? _m : '0.0.0';
66181
+ const currentFirmwareVersion = (_k = device.getCurrentFirmwareVersionString()) !== null && _k !== void 0 ? _k : '0.0.0';
66182
+ const currentBleVersion = (_l = device.getCurrentBLEFirmwareVersionString()) !== null && _l !== void 0 ? _l : '0.0.0';
66018
66183
  const deviceFirmwareType = device.getCurrentFirmwareType();
66019
66184
  let newVersionStatus;
66020
66185
  if (device.features && !device.isProtocolV2()) {
@@ -66092,7 +66257,7 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
66092
66257
  }
66093
66258
  },
66094
66259
  prepare: () => __awaiter(void 0, void 0, void 0, function* () {
66095
- var _o, _p, _q, _r, _s, _t;
66260
+ var _m, _o, _p, _q, _r, _s;
66096
66261
  if (method.deviceId && method.checkDeviceId && !deviceIdCheckedDuringUnlockPreflight) {
66097
66262
  const isSameDeviceID = yield checkLiveDeviceId(device, method.deviceId);
66098
66263
  if (!isSameDeviceID) {
@@ -66112,7 +66277,7 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
66112
66277
  require: support.require,
66113
66278
  });
66114
66279
  }
66115
- const passphraseStateSafety = yield device.checkPassphraseStateSafety((_o = method.payload) === null || _o === void 0 ? void 0 : _o.passphraseState, (_p = method.payload) === null || _p === void 0 ? void 0 : _p.useEmptyPassphrase, (_q = method.payload) === null || _q === void 0 ? void 0 : _q.skipPassphraseCheck, resolveDeriveCardano(method), (_r = method.protocolV2UnlockContext) === null || _r === void 0 ? void 0 : _r.preflightMainPinSelected);
66280
+ const passphraseStateSafety = yield device.checkPassphraseStateSafety((_m = method.payload) === null || _m === void 0 ? void 0 : _m.passphraseState, (_o = method.payload) === null || _o === void 0 ? void 0 : _o.useEmptyPassphrase, (_p = method.payload) === null || _p === void 0 ? void 0 : _p.skipPassphraseCheck, resolveDeriveCardano(method), (_q = method.protocolV2UnlockContext) === null || _q === void 0 ? void 0 : _q.preflightMainPinSelected);
66116
66281
  checkPassphraseEnableState(method, device.features);
66117
66282
  if (!passphraseStateSafety) {
66118
66283
  DevicePool.clearDeviceCache(method.payload.connectId);
@@ -66130,10 +66295,13 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
66130
66295
  ? e
66131
66296
  : hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'open safety check failed.');
66132
66297
  }
66133
- (_t = (_s = method.device) === null || _s === void 0 ? void 0 : _s.commands) === null || _t === void 0 ? void 0 : _t.checkDisposed();
66298
+ (_s = (_r = method.device) === null || _r === void 0 ? void 0 : _r.commands) === null || _s === void 0 ? void 0 : _s.checkDisposed();
66134
66299
  }),
66135
66300
  });
66136
66301
  messageResponse = createResponseMessage(method.responseID, true, response);
66302
+ if (method.connectId) {
66303
+ context.setPrePendingCallPromise(method.connectId, getPostCallPendingPromise(method, device));
66304
+ }
66137
66305
  requestQueue.resolveRequest(method.responseID, messageResponse);
66138
66306
  completeMethodRequestContext(method);
66139
66307
  }
@@ -66144,6 +66312,9 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
66144
66312
  }
66145
66313
  Log.debug(`Call API - Inner Method Run Error`, error);
66146
66314
  messageResponse = createResponseMessage(method.responseID, false, { error });
66315
+ if (method.connectId) {
66316
+ context.setPrePendingCallPromise(method.connectId, getPostCallPendingPromise(method, device));
66317
+ }
66147
66318
  requestQueue.resolveRequest(method.responseID, messageResponse);
66148
66319
  completeMethodRequestContext(method, error);
66149
66320
  if (error instanceof hdShared.HardwareError &&
@@ -66162,6 +66333,9 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
66162
66333
  });
66163
66334
  Log.debug('Call API - Device Run: ', device.mainId);
66164
66335
  const runOptions = Object.assign({ keepSession: method.payload.keepSession, skipInitialize: canSkipInitialize(method, device) }, parseInitOptions(method));
66336
+ if ((_j = method.abortSignal) === null || _j === void 0 ? void 0 : _j.aborted) {
66337
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallQueueActionCancelled);
66338
+ }
66165
66339
  const deviceRun = () => device.run(inner, runOptions);
66166
66340
  task.callPromise = hdShared.createDeferred(deviceRun);
66167
66341
  try {
@@ -66180,6 +66354,7 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
66180
66354
  requestQueue.rejectRequest(method.responseID, hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallMethodError, error.message));
66181
66355
  Log.debug('Call API - Run Error: ', error);
66182
66356
  completeMethodRequestContext(method, error);
66357
+ return messageResponse;
66183
66358
  }
66184
66359
  finally {
66185
66360
  preWarmCallbackTask === null || preWarmCallbackTask === void 0 ? void 0 : preWarmCallbackTask.resolve();
@@ -66329,11 +66504,15 @@ function isRetryableBleProtocolV2ProbeError(method, error) {
66329
66504
  message.includes('did not respond to expected protocol'));
66330
66505
  }
66331
66506
  function isRetryableBleConnectionError(method, error) {
66332
- var _a;
66507
+ var _a, _b;
66333
66508
  if ((_a = method.device) === null || _a === void 0 ? void 0 : _a.wasInterruptedByUser()) {
66334
66509
  return false;
66335
66510
  }
66336
66511
  const typedError = error;
66512
+ if ((typedError === null || typedError === void 0 ? void 0 : typedError.errorCode) === hdShared.HardwareErrorCode.BleTimeoutError &&
66513
+ ((_b = typedError.params) === null || _b === void 0 ? void 0 : _b.acquireDeadlineExceeded) === true) {
66514
+ return false;
66515
+ }
66337
66516
  return ((typedError === null || typedError === void 0 ? void 0 : typedError.errorCode) === hdShared.HardwareErrorCode.BleTimeoutError ||
66338
66517
  (typedError === null || typedError === void 0 ? void 0 : typedError.errorCode) === hdShared.HardwareErrorCode.BleConnectedError ||
66339
66518
  isRetryableBleProtocolV2ProbeError(method, error) ||
@@ -66346,10 +66525,11 @@ function isMissingDetectedProtocolV2Error(method, error) {
66346
66525
  typeof typedError.message === 'string' &&
66347
66526
  typedError.message.includes('Device protocol has not been detected'));
66348
66527
  }
66349
- function isProtocolV2PeerRemovedPairingError(method, error) {
66350
- return (method.payload.connectProtocol === 'V2' &&
66351
- (error === null || error === void 0 ? void 0 : error.errorCode) ===
66352
- hdShared.HardwareErrorCode.BlePeerRemovedPairingInformation);
66528
+ function isTerminalBleStaleBondError(error) {
66529
+ return hdShared.isBleStaleBondHardwareError(error);
66530
+ }
66531
+ function isDeviceIdentityMismatchError(error) {
66532
+ return ((error === null || error === void 0 ? void 0 : error.errorCode) === hdShared.HardwareErrorCode.DeviceCheckDeviceIdError);
66353
66533
  }
66354
66534
  const BLE_ACQUIRE_DEADLINE_MS = 60 * 1000;
66355
66535
  function raceBleAcquire(acquirePromise, abortSignal) {
@@ -66364,7 +66544,7 @@ function raceBleAcquire(acquirePromise, abortSignal) {
66364
66544
  fn();
66365
66545
  };
66366
66546
  const onAbort = () => settle(() => reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallQueueActionCancelled)));
66367
- const deadline = setTimeout(() => settle(() => reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleTimeoutError, `BLE acquire exceeded ${BLE_ACQUIRE_DEADLINE_MS}ms deadline`))), BLE_ACQUIRE_DEADLINE_MS);
66547
+ const deadline = setTimeout(() => settle(() => reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleTimeoutError, `BLE acquire exceeded ${BLE_ACQUIRE_DEADLINE_MS}ms deadline`, { acquireDeadlineExceeded: true }))), BLE_ACQUIRE_DEADLINE_MS);
66368
66548
  acquirePromise.then(value => settle(() => resolve(value)), error => settle(() => reject(error)));
66369
66549
  if (abortSignal) {
66370
66550
  if (abortSignal.aborted) {
@@ -66379,7 +66559,7 @@ function connectDeviceForBle(method, device, abortSignal, retryCount = 0) {
66379
66559
  var _a;
66380
66560
  return __awaiter(this, void 0, void 0, function* () {
66381
66561
  try {
66382
- if (device.wasInterruptedByUser()) {
66562
+ if ((abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.aborted) || device.wasInterruptedByUser()) {
66383
66563
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceInterruptedFromUser);
66384
66564
  }
66385
66565
  if (method.payload.forceProtocolDetection && device.hasDeviceAcquire()) {
@@ -66435,6 +66615,9 @@ function connectDeviceForBle(method, device, abortSignal, retryCount = 0) {
66435
66615
  }
66436
66616
  }
66437
66617
  catch (err) {
66618
+ if ((abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.aborted) || device.wasInterruptedByUser()) {
66619
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceInterruptedFromUser);
66620
+ }
66438
66621
  const requiresColdReconnect = isMissingDetectedProtocolV2Error(method, err);
66439
66622
  if ((hdShared.ERROR_CODES_REQUIRE_DISCONNECT.includes(err.errorCode) || requiresColdReconnect) &&
66440
66623
  device.mainId &&
@@ -66470,7 +66653,7 @@ const ensureConnected = (_context, method, connectId, pollingId, abortSignal) =>
66470
66653
  Log.debug(`EnsureConnected function start, MAX_RETRY_COUNT=${MAX_RETRY_COUNT}, POLL_INTERVAL_TIME=${POLL_INTERVAL_TIME} `);
66471
66654
  const poll = (time = POLL_INTERVAL_TIME) => __awaiter(void 0, void 0, void 0, function* () {
66472
66655
  return new Promise((resolve, reject) => __awaiter(void 0, void 0, void 0, function* () {
66473
- var _u;
66656
+ var _t;
66474
66657
  const abort = () => {
66475
66658
  if (abortSignal && abortSignal.aborted) {
66476
66659
  if (timer) {
@@ -66571,6 +66754,7 @@ const ensureConnected = (_context, method, connectId, pollingId, abortSignal) =>
66571
66754
  hdShared.HardwareErrorCode.BleDeviceBondedCanceled,
66572
66755
  hdShared.HardwareErrorCode.BleCharacteristicNotifyError,
66573
66756
  hdShared.HardwareErrorCode.BleTimeoutError,
66757
+ hdShared.HardwareErrorCode.PollingTimeout,
66574
66758
  hdShared.HardwareErrorCode.BleWriteCharacteristicError,
66575
66759
  hdShared.HardwareErrorCode.BleAlreadyConnected,
66576
66760
  hdShared.HardwareErrorCode.FirmwareUpdateLimitOneDevice,
@@ -66581,7 +66765,10 @@ const ensureConnected = (_context, method, connectId, pollingId, abortSignal) =>
66581
66765
  hdShared.HardwareErrorCode.DeviceInterruptedFromUser,
66582
66766
  hdShared.HardwareErrorCode.CallQueueActionCancelled,
66583
66767
  ].includes(error.errorCode) ||
66584
- isProtocolV2PeerRemovedPairingError(method, error)) {
66768
+ (env === 'react-native' &&
66769
+ [hdShared.HardwareErrorCode.BleDeviceDisconnected, hdShared.HardwareErrorCode.PollingTimeout].includes(error.errorCode)) ||
66770
+ isTerminalBleStaleBondError(error) ||
66771
+ isDeviceIdentityMismatchError(error)) {
66585
66772
  reject(error);
66586
66773
  return;
66587
66774
  }
@@ -66591,7 +66778,7 @@ const ensureConnected = (_context, method, connectId, pollingId, abortSignal) =>
66591
66778
  clearTimeout(timer);
66592
66779
  }
66593
66780
  Log.debug('EnsureConnected get to max try count, will return: ', tryCount);
66594
- if (DataManager.isBrowserWebUsb(env) && !((_u = method.payload) === null || _u === void 0 ? void 0 : _u.skipWebDevicePrompt)) {
66781
+ if (DataManager.isBrowserWebUsb(env) && !((_t = method.payload) === null || _t === void 0 ? void 0 : _t.skipWebDevicePrompt)) {
66595
66782
  postMessage(createUiMessage(UI_REQUEST.WEB_DEVICE_PROMPT_ACCESS_PERMISSION));
66596
66783
  reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.WebDeviceNotFoundOrNeedsPermission));
66597
66784
  }
@@ -66876,7 +67063,14 @@ class Core extends events.exports {
66876
67063
  this.prePendingCallPromises.delete(connectId);
66877
67064
  return;
66878
67065
  }
66879
- this.prePendingCallPromises.set(connectId, promise);
67066
+ const previous = this.prePendingCallPromises.get(connectId);
67067
+ const cleanupPromise = previous && previous !== promise
67068
+ ? Promise.all([previous, promise]).then(() => undefined)
67069
+ : promise;
67070
+ this.prePendingCallPromises.set(connectId, cleanupPromise);
67071
+ cleanupPromise.catch(error => {
67072
+ Log.warn('Device cancellation cleanup failed', { errorCode: error === null || error === void 0 ? void 0 : error.errorCode });
67073
+ });
66880
67074
  },
66881
67075
  removePrePendingCallPromise: (connectId, promise) => {
66882
67076
  if (this.prePendingCallPromises.get(connectId) === promise) {