@onekeyfe/hd-core 1.2.2-alpha.104 → 1.2.2-alpha.106

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 (42) hide show
  1. package/README.md +1 -1
  2. package/__tests__/AllNetworkGetAddressBase.tracing.test.ts +155 -2
  3. package/__tests__/core-error-output.test.ts +92 -1
  4. package/__tests__/device-lifecycle-events.test.ts +313 -2
  5. package/__tests__/open-wallet-session-error-response.test.ts +2 -2
  6. package/__tests__/open-wallet-session.test.ts +8 -411
  7. package/__tests__/public-device-state-api.test.ts +2 -7
  8. package/dist/api/GetFeatures.d.ts.map +1 -1
  9. package/dist/api/GetPassphraseState.d.ts.map +1 -1
  10. package/dist/api/OpenWalletSession.d.ts.map +1 -1
  11. package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts +3 -0
  12. package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
  13. package/dist/api/allnetwork/AllNetworkGetAddressByLoop.d.ts.map +1 -1
  14. package/dist/core/RequestQueue.d.ts +1 -0
  15. package/dist/core/RequestQueue.d.ts.map +1 -1
  16. package/dist/core/index.d.ts +1 -0
  17. package/dist/core/index.d.ts.map +1 -1
  18. package/dist/device/Device.d.ts +2 -0
  19. package/dist/device/Device.d.ts.map +1 -1
  20. package/dist/index.d.ts +17 -19
  21. package/dist/index.js +229 -138
  22. package/dist/types/api/getFeatures.d.ts.map +1 -1
  23. package/dist/types/api/getPassphraseState.d.ts.map +1 -1
  24. package/dist/types/api/openWalletSession.d.ts +1 -10
  25. package/dist/types/api/openWalletSession.d.ts.map +1 -1
  26. package/dist/types/params.d.ts.map +1 -1
  27. package/dist/utils/patch.d.ts +1 -1
  28. package/dist/utils/patch.d.ts.map +1 -1
  29. package/package.json +4 -4
  30. package/src/api/GetFeatures.ts +1 -0
  31. package/src/api/GetPassphraseState.ts +1 -0
  32. package/src/api/OpenWalletSession.ts +7 -77
  33. package/src/api/allnetwork/AllNetworkGetAddressBase.ts +56 -15
  34. package/src/api/allnetwork/AllNetworkGetAddressByLoop.ts +3 -0
  35. package/src/core/RequestQueue.ts +20 -0
  36. package/src/core/index.ts +95 -42
  37. package/src/data/messages/messages-protocol-v2.json +21 -0
  38. package/src/device/Device.ts +51 -27
  39. package/src/types/api/getFeatures.ts +2 -1
  40. package/src/types/api/getPassphraseState.ts +2 -5
  41. package/src/types/api/openWalletSession.ts +7 -19
  42. 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;
@@ -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,
@@ -46324,6 +46344,10 @@ class Device extends events.exports {
46324
46344
  }
46325
46345
  this.invalidateProtocolV2RuntimeState();
46326
46346
  }
46347
+ waitForRunCleanup() {
46348
+ var _a;
46349
+ return (_a = this.runCleanupPromise) !== null && _a !== void 0 ? _a : Promise.resolve();
46350
+ }
46327
46351
  run(fn, options) {
46328
46352
  return __awaiter(this, void 0, void 0, function* () {
46329
46353
  if (this.runPromise) {
@@ -46441,44 +46465,67 @@ class Device extends events.exports {
46441
46465
  });
46442
46466
  }
46443
46467
  interruptionFromUser() {
46444
- var _a, _b, _c, _d;
46445
- return __awaiter(this, void 0, void 0, function* () {
46446
- const error = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceInterruptedFromUser);
46447
- this.interruptedAttempt = this.connectionAttempt;
46448
- const cleanupPromise = this.runCleanupPromise;
46449
- const { cancelableAction } = this;
46450
- if (cancelableAction) {
46451
- yield cancelableAction(error);
46452
- }
46453
- else if (this.shouldSendFallbackProtocolCancel()) {
46454
- yield ((_b = (_a = this.commands) === null || _a === void 0 ? void 0 : _a.cancelDevice) === null || _b === void 0 ? void 0 : _b.call(_a).catch(cancelError => {
46455
- Log$h.debug('Protocol V2 fallback cancel error', cancelError);
46456
- }));
46468
+ var _a;
46469
+ const attempt = this.connectionAttempt;
46470
+ if (((_a = this.userInterruption) === null || _a === void 0 ? void 0 : _a.attempt) === attempt) {
46471
+ return this.userInterruption.promise;
46472
+ }
46473
+ const error = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceInterruptedFromUser);
46474
+ this.interruptedAttempt = attempt;
46475
+ const cleanupPromise = this.runCleanupPromise;
46476
+ const { cancelableAction, commands, runPromise, deviceConnector, mainId } = this;
46477
+ const sendFallbackCancel = this.shouldSendFallbackProtocolCancel();
46478
+ const acquired = this.hasDeviceAcquire();
46479
+ const promise = (() => __awaiter(this, void 0, void 0, function* () {
46480
+ var _b;
46481
+ try {
46482
+ if (cancelableAction) {
46483
+ yield cancelableAction(error);
46484
+ }
46485
+ else if (sendFallbackCancel) {
46486
+ yield ((_b = commands === null || commands === void 0 ? void 0 : commands.cancelDevice) === null || _b === void 0 ? void 0 : _b.call(commands).catch(cancelError => {
46487
+ Log$h.debug('Protocol V2 fallback cancel error', cancelError);
46488
+ }));
46489
+ }
46490
+ else if (!acquired) {
46491
+ if (mainId && (deviceConnector === null || deviceConnector === void 0 ? void 0 : deviceConnector.disconnect)) {
46492
+ yield deviceConnector.disconnect(mainId);
46493
+ }
46494
+ if (this.connectionAttempt === attempt)
46495
+ this.markTransportDisconnected();
46496
+ }
46497
+ yield (commands === null || commands === void 0 ? void 0 : commands.cancel());
46457
46498
  }
46458
- else if (!this.hasDeviceAcquire()) {
46459
- if (this.mainId && ((_c = this.deviceConnector) === null || _c === void 0 ? void 0 : _c.disconnect)) {
46460
- yield this.deviceConnector.disconnect(this.mainId).catch(disconnectError => {
46461
- Log$h.debug('Ignored disconnect during user cancel without acquire', disconnectError);
46499
+ catch (cleanupError) {
46500
+ Log$h.warn('User cancellation cleanup failed; disconnecting device', cleanupError);
46501
+ if (mainId && (deviceConnector === null || deviceConnector === void 0 ? void 0 : deviceConnector.disconnect)) {
46502
+ yield deviceConnector.disconnect(mainId).catch(disconnectError => {
46503
+ Log$h.debug('User cancellation fallback disconnect failed', disconnectError);
46462
46504
  });
46463
46505
  }
46464
- this.markTransportDisconnected();
46506
+ if (this.connectionAttempt === attempt)
46507
+ this.markTransportDisconnected();
46465
46508
  }
46466
- yield ((_d = this.commands) === null || _d === void 0 ? void 0 : _d.cancel());
46467
- if (this.runPromise) {
46468
- this.runPromise.reject(error);
46469
- this.runPromise = null;
46509
+ finally {
46510
+ runPromise === null || runPromise === void 0 ? void 0 : runPromise.reject(error);
46511
+ if (this.runPromise === runPromise)
46512
+ this.runPromise = null;
46513
+ yield (cleanupPromise === null || cleanupPromise === void 0 ? void 0 : cleanupPromise.catch(() => undefined));
46470
46514
  }
46471
- yield (cleanupPromise === null || cleanupPromise === void 0 ? void 0 : cleanupPromise.catch(() => undefined));
46472
- });
46515
+ }))();
46516
+ this.userInterruption = { attempt, promise };
46517
+ return promise;
46473
46518
  }
46474
46519
  setCancelableAction(callback) {
46475
- this.cancelableAction = (e) => callback(e)
46520
+ const action = (e) => callback(e)
46476
46521
  .catch(e2 => {
46477
46522
  Log$h.debug('cancelableAction error', e2);
46478
46523
  })
46479
46524
  .finally(() => {
46480
- this.clearCancelableAction();
46525
+ if (this.cancelableAction === action)
46526
+ this.clearCancelableAction();
46481
46527
  });
46528
+ this.cancelableAction = action;
46482
46529
  }
46483
46530
  clearCancelableAction() {
46484
46531
  this.cancelableAction = undefined;
@@ -47588,15 +47635,6 @@ function validateResult(result, nonNullableFields, options) {
47588
47635
  }
47589
47636
  }
47590
47637
 
47591
- const requiredString = (value, name) => {
47592
- if (value === undefined || value === null) {
47593
- throw invalidParameter(`Missing required parameter: ${name}`);
47594
- }
47595
- if (typeof value !== 'string' || !value.trim()) {
47596
- throw invalidParameter(`Parameter [${name}] must be a non-empty string.`);
47597
- }
47598
- return value.trim();
47599
- };
47600
47638
  const wasResumed = (session) => !!session &&
47601
47639
  typeof session === 'object' &&
47602
47640
  'resumed' in session &&
@@ -47618,25 +47656,16 @@ const normalizeParams = (payload) => {
47618
47656
  throw invalidParameter('Parameter [mode] is required.');
47619
47657
  }
47620
47658
  if (payload.mode !== OpenWalletSessionMode.Standard &&
47621
- payload.mode !== OpenWalletSessionMode.SelectHidden &&
47622
- payload.mode !== OpenWalletSessionMode.ResumeHidden) {
47623
- throw invalidParameter('Parameter [mode] must be one of standard, select-hidden, or resume-hidden.');
47659
+ payload.mode !== OpenWalletSessionMode.SelectHidden) {
47660
+ throw invalidParameter('Parameter [mode] must be one of standard or select-hidden.');
47624
47661
  }
47625
47662
  if (payload.useEmptyPassphrase !== undefined || payload.initSession !== undefined) {
47626
47663
  throw invalidParameter('Legacy parameters [useEmptyPassphrase] and [initSession] are not supported by openWalletSession.');
47627
47664
  }
47628
- if (payload.mode === OpenWalletSessionMode.Standard ||
47629
- payload.mode === OpenWalletSessionMode.SelectHidden) {
47630
- if (payload.deviceId !== undefined || payload.passphraseState !== undefined) {
47631
- throw invalidParameter('Parameters [deviceId] and [passphraseState] are only allowed with mode [resume-hidden].');
47632
- }
47633
- return { mode: payload.mode };
47665
+ if (payload.deviceId !== undefined || payload.passphraseState !== undefined) {
47666
+ throw invalidParameter('Parameters [deviceId] and [passphraseState] are not supported by openWalletSession. Pass passphraseState on later address and signing calls.');
47634
47667
  }
47635
- return {
47636
- mode: OpenWalletSessionMode.ResumeHidden,
47637
- deviceId: requiredString(payload.deviceId, 'deviceId'),
47638
- passphraseState: requiredString(payload.passphraseState, 'passphraseState'),
47639
- };
47668
+ return { mode: payload.mode };
47640
47669
  };
47641
47670
  class OpenWalletSession extends BaseMethod {
47642
47671
  getSupportedProtocols() {
@@ -47739,43 +47768,6 @@ class OpenWalletSession extends BaseMethod {
47739
47768
  resumed: wasResumed(session),
47740
47769
  };
47741
47770
  }
47742
- if (this.params.mode === OpenWalletSessionMode.ResumeHidden) {
47743
- if (isProtocolV2) {
47744
- yield ensureProtocolV2WalletStatus();
47745
- const refreshedDeviceId = requireDeviceId();
47746
- if (refreshedDeviceId !== this.params.deviceId) {
47747
- deviceWalletSessionStore.delete(this.params.deviceId, this.params.passphraseState);
47748
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceCheckDeviceIdError);
47749
- }
47750
- }
47751
- else if (requireDeviceId() !== this.params.deviceId) {
47752
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceCheckDeviceIdError);
47753
- }
47754
- this.device.passphraseState = this.params.passphraseState;
47755
- const cachedSessionId = deviceWalletSessionStore.get(this.params.deviceId, this.params.passphraseState);
47756
- if (!cachedSessionId && !isProtocolV2) {
47757
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.WalletSessionInvalid);
47758
- }
47759
- if (!isProtocolV2) {
47760
- yield this.device.initialize({
47761
- deviceId: this.params.deviceId,
47762
- passphraseState: this.params.passphraseState,
47763
- });
47764
- }
47765
- const session = isProtocolV2
47766
- ? yield getProtocolV2WalletSession(this.device, {
47767
- expectedPassphraseState: this.params.passphraseState,
47768
- })
47769
- : yield getPassphraseStateWithRefreshDeviceInfo(this.device, {
47770
- expectPassphraseState: this.params.passphraseState,
47771
- });
47772
- const deviceId = requireDeviceId();
47773
- if (session.passphraseState !== this.params.passphraseState) {
47774
- this.device.clearInternalState();
47775
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceCheckPassphraseStateError);
47776
- }
47777
- return Object.assign(Object.assign({ protocol, walletType: 'hidden', deviceId }, requireHiddenWalletResponse(session)), { resumed: wasResumed(session) || (!isProtocolV2 && session.newSession === cachedSessionId) });
47778
- }
47779
47771
  this.device.passphraseState = undefined;
47780
47772
  const walletStatus = yield ensureProtocolV2WalletStatus();
47781
47773
  if (isProtocolV2 && walletStatus.status.passphraseProtection !== true) {
@@ -55908,6 +55900,7 @@ class AllNetworkGetAddressBase extends BaseMethod {
55908
55900
  constructor() {
55909
55901
  super(...arguments);
55910
55902
  this.abortController = null;
55903
+ this.loadingCleanupInBackground = false;
55911
55904
  }
55912
55905
  getSupportedProtocols() {
55913
55906
  return ['V1', 'V2'];
@@ -56045,27 +56038,61 @@ class AllNetworkGetAddressBase extends BaseMethod {
56045
56038
  return result;
56046
56039
  });
56047
56040
  }
56048
- run() {
56041
+ stopAllNetworkLoading(canSend = true) {
56049
56042
  return __awaiter(this, void 0, void 0, function* () {
56050
- const res = yield this.device.commands.typedCall('GetPublicKey', 'PublicKey', {
56051
- address_n: [toHardened(44), toHardened(1), toHardened(0)],
56052
- coin_name: 'Testnet',
56053
- script_type: 'SPENDADDRESS',
56054
- show_display: false,
56055
- });
56056
- if (!this.device.isProtocolV2()) {
56057
- this.postMessage(createUiMessage(UI_REQUEST.CLOSE_UI_PIN_WINDOW));
56043
+ const commands = this.loadingCommands;
56044
+ this.loadingCommands = undefined;
56045
+ if (!canSend || !commands || commands.disposed || commands !== this.device.commands)
56046
+ return;
56047
+ try {
56048
+ yield commands.typedCall('DeviceAnimationControl', 'Success', {
56049
+ action: hdTransport.Messages.DeviceAnimationAction.AnimationAction_Stop,
56050
+ });
56058
56051
  }
56059
- if (res.message.root_fingerprint == null) {
56060
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallMethodInvalidParameter);
56052
+ catch (_a) {
56061
56053
  }
56062
- this.abortController = new AbortController();
56063
- return this.getAllNetworkAddress(res.message.root_fingerprint).catch(e => {
56054
+ });
56055
+ }
56056
+ run() {
56057
+ return __awaiter(this, void 0, void 0, function* () {
56058
+ this.loadingCleanupInBackground = false;
56059
+ try {
56060
+ if (this.device.isProtocolV2() && this.device.getCurrentDeviceType() === hdShared.EDeviceType.Pro2) {
56061
+ const protocolInfo = yield this.device.ensureProtocolV2RuntimeContext();
56062
+ if (supportsProtocolV2Message(protocolInfo, 60461)) {
56063
+ const { commands } = this.device;
56064
+ yield commands.typedCall('DeviceAnimationControl', 'Success', {
56065
+ action: hdTransport.Messages.DeviceAnimationAction.AnimationAction_Start,
56066
+ });
56067
+ this.loadingCommands = commands;
56068
+ }
56069
+ }
56070
+ const res = yield this.device.commands.typedCall('GetPublicKey', 'PublicKey', {
56071
+ address_n: [toHardened(44), toHardened(1), toHardened(0)],
56072
+ coin_name: 'Testnet',
56073
+ script_type: 'SPENDADDRESS',
56074
+ show_display: false,
56075
+ });
56076
+ if (!this.device.isProtocolV2()) {
56077
+ this.postMessage(createUiMessage(UI_REQUEST.CLOSE_UI_PIN_WINDOW));
56078
+ }
56079
+ if (res.message.root_fingerprint == null) {
56080
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallMethodInvalidParameter);
56081
+ }
56082
+ this.abortController = new AbortController();
56083
+ return yield this.getAllNetworkAddress(res.message.root_fingerprint);
56084
+ }
56085
+ catch (e) {
56086
+ yield this.stopAllNetworkLoading(false);
56064
56087
  if (e instanceof hdShared.HardwareError && e.errorCode === hdShared.HardwareErrorCode.RepeatUnlocking) {
56065
56088
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RepeatUnlocking, e.message);
56066
56089
  }
56067
56090
  throw e;
56068
- });
56091
+ }
56092
+ finally {
56093
+ if (!this.loadingCleanupInBackground)
56094
+ yield this.stopAllNetworkLoading();
56095
+ }
56069
56096
  });
56070
56097
  }
56071
56098
  }
@@ -56192,6 +56219,7 @@ class AllNetworkGetAddressByLoop extends AllNetworkGetAddressBase {
56192
56219
  throw new Error('callbackIdFinish is required');
56193
56220
  }
56194
56221
  const bundle = this.payload.bundle || [this.payload];
56222
+ this.loadingCleanupInBackground = true;
56195
56223
  const callbackPromise = this.processCallbacksInBackground(bundle, rootFingerprint, callbackId, callbackIdFinish);
56196
56224
  this.device.pendingCallbackPromise = hdShared.createDeferred(callbackPromise);
56197
56225
  if (this.context && this.payload.connectId) {
@@ -56232,6 +56260,7 @@ class AllNetworkGetAddressByLoop extends AllNetworkGetAddressBase {
56232
56260
  });
56233
56261
  }
56234
56262
  catch (error) {
56263
+ yield this.stopAllNetworkLoading(false);
56235
56264
  let errorCode = error.errorCode || error.code;
56236
56265
  let errorMessage = error.message;
56237
56266
  if (error instanceof hdShared.HardwareError) {
@@ -56259,6 +56288,7 @@ class AllNetworkGetAddressByLoop extends AllNetworkGetAddressBase {
56259
56288
  });
56260
56289
  }
56261
56290
  finally {
56291
+ yield this.stopAllNetworkLoading();
56262
56292
  (_c = this.context) === null || _c === void 0 ? void 0 : _c.cancelCallbackTasks(this.payload.connectId);
56263
56293
  this.abortController = null;
56264
56294
  }
@@ -65584,6 +65614,29 @@ class RequestQueue {
65584
65614
  getTask(requestId) {
65585
65615
  return this.requestQueue.get(requestId);
65586
65616
  }
65617
+ waitForTask(task, pending) {
65618
+ return __awaiter(this, void 0, void 0, function* () {
65619
+ const signal = task.method.abortSignal;
65620
+ const cancellationError = () => hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallQueueActionCancelled);
65621
+ if (signal === null || signal === void 0 ? void 0 : signal.aborted)
65622
+ throw cancellationError();
65623
+ let onAbort;
65624
+ try {
65625
+ const cancelled = new Promise((_, reject) => {
65626
+ onAbort = () => reject(cancellationError());
65627
+ signal === null || signal === void 0 ? void 0 : signal.addEventListener('abort', onAbort, { once: true });
65628
+ });
65629
+ const result = yield Promise.race([pending(), cancelled]);
65630
+ if (signal === null || signal === void 0 ? void 0 : signal.aborted)
65631
+ throw cancellationError();
65632
+ return result;
65633
+ }
65634
+ finally {
65635
+ if (onAbort)
65636
+ signal === null || signal === void 0 ? void 0 : signal.removeEventListener('abort', onAbort);
65637
+ }
65638
+ });
65639
+ }
65587
65640
  getAbortController(requestId) {
65588
65641
  var _a;
65589
65642
  return (_a = this.requestQueue.get(requestId)) === null || _a === void 0 ? void 0 : _a.abortController;
@@ -65784,6 +65837,7 @@ const createUiProgressMessageFilter = (intervalMs = DEFAULT_UI_PROGRESS_INTERVAL
65784
65837
  const Log = getLogger(exports.LoggerNames.Core);
65785
65838
  const PRE_INITIALIZE_TTL_MS = 60 * 1000;
65786
65839
  const PRE_PENDING_CALL_TIMEOUT_MS = 15 * 1000;
65840
+ const PRO2_USB_SIGNING_COOLDOWN_MS = 1000;
65787
65841
  const preWarmInflight = new Map();
65788
65842
  const preWarmDoneAt = new Map();
65789
65843
  function resolveDeriveCardano(method) {
@@ -65950,33 +66004,37 @@ const waitForPendingPromise = (connectId, getPrePendingCallPromise, removePrePen
65950
66004
  if (pendingPromise) {
65951
66005
  Log.debug('pre pending call promise before call method, wait for it');
65952
66006
  let timer;
65953
- let timedOut = false;
65954
66007
  try {
65955
66008
  yield Promise.race([
65956
66009
  pendingPromise,
65957
- new Promise(resolve => {
66010
+ new Promise((_, reject) => {
65958
66011
  timer = setTimeout(() => {
65959
- timedOut = true;
65960
- resolve();
66012
+ reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceBusy, 'Previous device cancellation is still draining'));
65961
66013
  }, PRE_PENDING_CALL_TIMEOUT_MS);
65962
66014
  }),
65963
66015
  ]);
65964
- }
65965
- catch (error) {
66016
+ removePrePendingCallPromise === null || removePrePendingCallPromise === void 0 ? void 0 : removePrePendingCallPromise(connectId, pendingPromise);
65966
66017
  }
65967
66018
  finally {
65968
66019
  if (timer)
65969
66020
  clearTimeout(timer);
65970
- removePrePendingCallPromise === null || removePrePendingCallPromise === void 0 ? void 0 : removePrePendingCallPromise(connectId, pendingPromise);
65971
- }
65972
- if (timedOut) {
65973
- Log.warn('pre pending call promise timed out before call method', { connectId });
65974
66021
  }
65975
66022
  Log.debug('pre pending call promise before call method done');
65976
66023
  }
65977
66024
  });
66025
+ function getPostCallPendingPromise(method, device) {
66026
+ const cleanupPromise = device.waitForRunCleanup();
66027
+ const env = DataManager.getSettings('env');
66028
+ const deviceType = device.getCurrentDeviceType();
66029
+ const requiresSigningCooldown = method.name.includes('Sign') &&
66030
+ (deviceType === hdShared.EDeviceType.Pro2 || deviceType === hdShared.EDeviceType.Neo) &&
66031
+ (DataManager.isBrowserWebUsb(env) || DataManager.isDesktopWebUsb(env) || env === 'node-usb');
66032
+ return requiresSigningCooldown
66033
+ ? cleanupPromise.then(() => wait(PRO2_USB_SIGNING_COOLDOWN_MS)).then(() => undefined)
66034
+ : cleanupPromise;
66035
+ }
65978
66036
  const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, void 0, function* () {
65979
- var _d, _e, _f, _g, _h, _j, _k;
66037
+ var _d, _e, _f, _g, _h, _j;
65980
66038
  let messageResponse;
65981
66039
  const { requestQueue, getPrePendingCallPromise, removePrePendingCallPromise } = context;
65982
66040
  updateMethodRequestContext(method, { status: 'running' });
@@ -65990,21 +66048,27 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
65990
66048
  Log.debug('passphrase state change, clear device cache');
65991
66049
  DevicePool.clearDeviceCache(method.payload.connectId);
65992
66050
  }
65993
- if (method.connectId) {
65994
- yield context.waitForCallbackTasks(method.connectId);
65995
- }
65996
- yield waitForPendingPromise((_d = method.connectId) !== null && _d !== void 0 ? _d : '', getPrePendingCallPromise, removePrePendingCallPromise);
65997
66051
  const task = requestQueue.createTask(method);
65998
66052
  let preWarmCallbackTask;
65999
- if (method.isPreWarmSignal && method.connectId) {
66000
- preWarmCallbackTask = hdShared.createDeferred();
66001
- context.registerCallbackTask(method.connectId, preWarmCallbackTask);
66002
- }
66003
66053
  let device;
66004
66054
  try {
66005
- const connectId = (_e = method.connectId) !== null && _e !== void 0 ? _e : '';
66055
+ const connectId = (_d = method.connectId) !== null && _d !== void 0 ? _d : '';
66056
+ if (connectId) {
66057
+ yield requestQueue.waitForTask(task, () => context.waitForCallbackTasks(connectId));
66058
+ }
66059
+ yield requestQueue.waitForTask(task, () => {
66060
+ var _a;
66061
+ return waitForPendingPromise((_a = method.connectId) !== null && _a !== void 0 ? _a : '', getPrePendingCallPromise, removePrePendingCallPromise);
66062
+ });
66063
+ if (method.isPreWarmSignal && method.connectId) {
66064
+ preWarmCallbackTask = hdShared.createDeferred();
66065
+ context.registerCallbackTask(method.connectId, preWarmCallbackTask);
66066
+ }
66006
66067
  const pollingId = pollingManager.start(connectId);
66007
- device = yield ensureConnected(context, method, connectId, pollingId, (_f = task.abortController) === null || _f === void 0 ? void 0 : _f.signal);
66068
+ device = yield ensureConnected(context, method, connectId, pollingId, method.abortSignal);
66069
+ if ((_e = method.abortSignal) === null || _e === void 0 ? void 0 : _e.aborted) {
66070
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallQueueActionCancelled);
66071
+ }
66008
66072
  }
66009
66073
  catch (e) {
66010
66074
  preWarmCallbackTask === null || preWarmCallbackTask === void 0 ? void 0 : preWarmCallbackTask.resolve();
@@ -66019,7 +66083,7 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
66019
66083
  requestQueue.releaseTask(method.responseID);
66020
66084
  return createResponseMessage(method.responseID, false, { error: e });
66021
66085
  }
66022
- if ((_g = method.payload) === null || _g === void 0 ? void 0 : _g.onlyConnectBleDevice) {
66086
+ if ((_f = method.payload) === null || _f === void 0 ? void 0 : _f.onlyConnectBleDevice) {
66023
66087
  preWarmCallbackTask === null || preWarmCallbackTask === void 0 ? void 0 : preWarmCallbackTask.resolve();
66024
66088
  Log.debug('Call API - only connect ble device: ', device === null || device === void 0 ? void 0 : device.mainId);
66025
66089
  completeMethodRequestContext(method);
@@ -66027,11 +66091,11 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
66027
66091
  return createResponseMessage(method.responseID, true, null);
66028
66092
  }
66029
66093
  Log.debug('Call API - setDevice: ', device.mainId);
66030
- (_h = method.setDevice) === null || _h === void 0 ? void 0 : _h.call(method, device);
66094
+ (_g = method.setDevice) === null || _g === void 0 ? void 0 : _g.call(method, device);
66031
66095
  method.context = context;
66032
66096
  updateMethodRequestContext(method, {
66033
66097
  deviceInstanceId: device.instanceId,
66034
- commandsInstanceId: (_j = device.commands) === null || _j === void 0 ? void 0 : _j.instanceId,
66098
+ commandsInstanceId: (_h = device.commands) === null || _h === void 0 ? void 0 : _h.instanceId,
66035
66099
  });
66036
66100
  const activeRequests = getActiveRequestsByDeviceInstance(device.instanceId);
66037
66101
  if (activeRequests.length > 0) {
@@ -66057,17 +66121,21 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
66057
66121
  device.beginProtocolV2UiInteraction();
66058
66122
  device.on(DEVICE.SELECT_DEVICE_FOR_SWITCH_FIRMWARE_WEB_DEVICE, onSelectDeviceForSwitchFirmwareWebDeviceHandler);
66059
66123
  try {
66060
- if (method.connectId) {
66061
- yield context.waitForCallbackTasks(method.connectId, preWarmCallbackTask);
66124
+ const { connectId } = method;
66125
+ if (connectId) {
66126
+ yield requestQueue.waitForTask(task, () => context.waitForCallbackTasks(connectId, preWarmCallbackTask));
66062
66127
  }
66063
- yield waitForPendingPromise((_k = method.connectId) !== null && _k !== void 0 ? _k : '', getPrePendingCallPromise, removePrePendingCallPromise);
66128
+ yield requestQueue.waitForTask(task, () => {
66129
+ var _a;
66130
+ return waitForPendingPromise((_a = method.connectId) !== null && _a !== void 0 ? _a : '', getPrePendingCallPromise, removePrePendingCallPromise);
66131
+ });
66064
66132
  const inner = () => __awaiter(void 0, void 0, void 0, function* () {
66065
- var _l, _m;
66133
+ var _k, _l;
66066
66134
  method.assertProtocolSupported(device.getProtocol(), device.getCurrentFirmwareType());
66067
66135
  protocolV2Operation = device.isProtocolV2();
66068
66136
  const versionRange = device.getCurrentMethodVersionRange(type => method.getVersionRange()[type]);
66069
- const currentFirmwareVersion = (_l = device.getCurrentFirmwareVersionString()) !== null && _l !== void 0 ? _l : '0.0.0';
66070
- const currentBleVersion = (_m = device.getCurrentBLEFirmwareVersionString()) !== null && _m !== void 0 ? _m : '0.0.0';
66137
+ const currentFirmwareVersion = (_k = device.getCurrentFirmwareVersionString()) !== null && _k !== void 0 ? _k : '0.0.0';
66138
+ const currentBleVersion = (_l = device.getCurrentBLEFirmwareVersionString()) !== null && _l !== void 0 ? _l : '0.0.0';
66071
66139
  const deviceFirmwareType = device.getCurrentFirmwareType();
66072
66140
  let newVersionStatus;
66073
66141
  if (device.features && !device.isProtocolV2()) {
@@ -66145,7 +66213,7 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
66145
66213
  }
66146
66214
  },
66147
66215
  prepare: () => __awaiter(void 0, void 0, void 0, function* () {
66148
- var _o, _p, _q, _r, _s, _t;
66216
+ var _m, _o, _p, _q, _r, _s;
66149
66217
  if (method.deviceId && method.checkDeviceId && !deviceIdCheckedDuringUnlockPreflight) {
66150
66218
  const isSameDeviceID = yield checkLiveDeviceId(device, method.deviceId);
66151
66219
  if (!isSameDeviceID) {
@@ -66165,7 +66233,7 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
66165
66233
  require: support.require,
66166
66234
  });
66167
66235
  }
66168
- 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);
66236
+ 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);
66169
66237
  checkPassphraseEnableState(method, device.features);
66170
66238
  if (!passphraseStateSafety) {
66171
66239
  DevicePool.clearDeviceCache(method.payload.connectId);
@@ -66183,10 +66251,13 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
66183
66251
  ? e
66184
66252
  : hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'open safety check failed.');
66185
66253
  }
66186
- (_t = (_s = method.device) === null || _s === void 0 ? void 0 : _s.commands) === null || _t === void 0 ? void 0 : _t.checkDisposed();
66254
+ (_s = (_r = method.device) === null || _r === void 0 ? void 0 : _r.commands) === null || _s === void 0 ? void 0 : _s.checkDisposed();
66187
66255
  }),
66188
66256
  });
66189
66257
  messageResponse = createResponseMessage(method.responseID, true, response);
66258
+ if (method.connectId) {
66259
+ context.setPrePendingCallPromise(method.connectId, getPostCallPendingPromise(method, device));
66260
+ }
66190
66261
  requestQueue.resolveRequest(method.responseID, messageResponse);
66191
66262
  completeMethodRequestContext(method);
66192
66263
  }
@@ -66197,6 +66268,9 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
66197
66268
  }
66198
66269
  Log.debug(`Call API - Inner Method Run Error`, error);
66199
66270
  messageResponse = createResponseMessage(method.responseID, false, { error });
66271
+ if (method.connectId) {
66272
+ context.setPrePendingCallPromise(method.connectId, getPostCallPendingPromise(method, device));
66273
+ }
66200
66274
  requestQueue.resolveRequest(method.responseID, messageResponse);
66201
66275
  completeMethodRequestContext(method, error);
66202
66276
  if (error instanceof hdShared.HardwareError &&
@@ -66215,6 +66289,9 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
66215
66289
  });
66216
66290
  Log.debug('Call API - Device Run: ', device.mainId);
66217
66291
  const runOptions = Object.assign({ keepSession: method.payload.keepSession, skipInitialize: canSkipInitialize(method, device) }, parseInitOptions(method));
66292
+ if ((_j = method.abortSignal) === null || _j === void 0 ? void 0 : _j.aborted) {
66293
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallQueueActionCancelled);
66294
+ }
66218
66295
  const deviceRun = () => device.run(inner, runOptions);
66219
66296
  task.callPromise = hdShared.createDeferred(deviceRun);
66220
66297
  try {
@@ -66233,6 +66310,7 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
66233
66310
  requestQueue.rejectRequest(method.responseID, hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallMethodError, error.message));
66234
66311
  Log.debug('Call API - Run Error: ', error);
66235
66312
  completeMethodRequestContext(method, error);
66313
+ return messageResponse;
66236
66314
  }
66237
66315
  finally {
66238
66316
  preWarmCallbackTask === null || preWarmCallbackTask === void 0 ? void 0 : preWarmCallbackTask.resolve();
@@ -66437,7 +66515,7 @@ function connectDeviceForBle(method, device, abortSignal, retryCount = 0) {
66437
66515
  var _a;
66438
66516
  return __awaiter(this, void 0, void 0, function* () {
66439
66517
  try {
66440
- if (device.wasInterruptedByUser()) {
66518
+ if ((abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.aborted) || device.wasInterruptedByUser()) {
66441
66519
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceInterruptedFromUser);
66442
66520
  }
66443
66521
  if (method.payload.forceProtocolDetection && device.hasDeviceAcquire()) {
@@ -66493,6 +66571,9 @@ function connectDeviceForBle(method, device, abortSignal, retryCount = 0) {
66493
66571
  }
66494
66572
  }
66495
66573
  catch (err) {
66574
+ if ((abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.aborted) || device.wasInterruptedByUser()) {
66575
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceInterruptedFromUser);
66576
+ }
66496
66577
  const requiresColdReconnect = isMissingDetectedProtocolV2Error(method, err);
66497
66578
  if ((hdShared.ERROR_CODES_REQUIRE_DISCONNECT.includes(err.errorCode) || requiresColdReconnect) &&
66498
66579
  device.mainId &&
@@ -66528,7 +66609,7 @@ const ensureConnected = (_context, method, connectId, pollingId, abortSignal) =>
66528
66609
  Log.debug(`EnsureConnected function start, MAX_RETRY_COUNT=${MAX_RETRY_COUNT}, POLL_INTERVAL_TIME=${POLL_INTERVAL_TIME} `);
66529
66610
  const poll = (time = POLL_INTERVAL_TIME) => __awaiter(void 0, void 0, void 0, function* () {
66530
66611
  return new Promise((resolve, reject) => __awaiter(void 0, void 0, void 0, function* () {
66531
- var _u;
66612
+ var _t;
66532
66613
  const abort = () => {
66533
66614
  if (abortSignal && abortSignal.aborted) {
66534
66615
  if (timer) {
@@ -66629,6 +66710,7 @@ const ensureConnected = (_context, method, connectId, pollingId, abortSignal) =>
66629
66710
  hdShared.HardwareErrorCode.BleDeviceBondedCanceled,
66630
66711
  hdShared.HardwareErrorCode.BleCharacteristicNotifyError,
66631
66712
  hdShared.HardwareErrorCode.BleTimeoutError,
66713
+ hdShared.HardwareErrorCode.PollingTimeout,
66632
66714
  hdShared.HardwareErrorCode.BleWriteCharacteristicError,
66633
66715
  hdShared.HardwareErrorCode.BleAlreadyConnected,
66634
66716
  hdShared.HardwareErrorCode.FirmwareUpdateLimitOneDevice,
@@ -66639,6 +66721,8 @@ const ensureConnected = (_context, method, connectId, pollingId, abortSignal) =>
66639
66721
  hdShared.HardwareErrorCode.DeviceInterruptedFromUser,
66640
66722
  hdShared.HardwareErrorCode.CallQueueActionCancelled,
66641
66723
  ].includes(error.errorCode) ||
66724
+ (env === 'react-native' &&
66725
+ [hdShared.HardwareErrorCode.BleDeviceDisconnected, hdShared.HardwareErrorCode.PollingTimeout].includes(error.errorCode)) ||
66642
66726
  isTerminalBleStaleBondError(error) ||
66643
66727
  isDeviceIdentityMismatchError(error)) {
66644
66728
  reject(error);
@@ -66650,7 +66734,7 @@ const ensureConnected = (_context, method, connectId, pollingId, abortSignal) =>
66650
66734
  clearTimeout(timer);
66651
66735
  }
66652
66736
  Log.debug('EnsureConnected get to max try count, will return: ', tryCount);
66653
- if (DataManager.isBrowserWebUsb(env) && !((_u = method.payload) === null || _u === void 0 ? void 0 : _u.skipWebDevicePrompt)) {
66737
+ if (DataManager.isBrowserWebUsb(env) && !((_t = method.payload) === null || _t === void 0 ? void 0 : _t.skipWebDevicePrompt)) {
66654
66738
  postMessage(createUiMessage(UI_REQUEST.WEB_DEVICE_PROMPT_ACCESS_PERMISSION));
66655
66739
  reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.WebDeviceNotFoundOrNeedsPermission));
66656
66740
  }
@@ -66935,7 +67019,14 @@ class Core extends events.exports {
66935
67019
  this.prePendingCallPromises.delete(connectId);
66936
67020
  return;
66937
67021
  }
66938
- this.prePendingCallPromises.set(connectId, promise);
67022
+ const previous = this.prePendingCallPromises.get(connectId);
67023
+ const cleanupPromise = previous && previous !== promise
67024
+ ? Promise.all([previous, promise]).then(() => undefined)
67025
+ : promise;
67026
+ this.prePendingCallPromises.set(connectId, cleanupPromise);
67027
+ cleanupPromise.catch(error => {
67028
+ Log.warn('Device cancellation cleanup failed', { errorCode: error === null || error === void 0 ? void 0 : error.errorCode });
67029
+ });
66939
67030
  },
66940
67031
  removePrePendingCallPromise: (connectId, promise) => {
66941
67032
  if (this.prePendingCallPromises.get(connectId) === promise) {
@@ -1 +1 @@
1
- {"version":3,"file":"getFeatures.d.ts","sourceRoot":"","sources":["../../../src/types/api/getFeatures.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACxD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAK1C,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,YAAY,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC"}
1
+ {"version":3,"file":"getFeatures.d.ts","sourceRoot":"","sources":["../../../src/types/api/getFeatures.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACxD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAM1C,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,YAAY,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC"}