@onekeyfe/hd-core 1.2.3-alpha.1 → 1.2.3-alpha.11

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 (58) hide show
  1. package/README.md +1 -1
  2. package/__tests__/AllNetworkGetAddressBase.tracing.test.ts +503 -10
  3. package/__tests__/core-error-output.test.ts +169 -1
  4. package/__tests__/device-lifecycle-events.test.ts +350 -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__/protocol-v2.test.ts +51 -0
  8. package/__tests__/public-device-state-api.test.ts +2 -7
  9. package/__tests__/search-devices.test.ts +196 -8
  10. package/__tests__/sol-sign-offchain-message.test.ts +0 -8
  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/SearchDevices.d.ts +2 -15
  15. package/dist/api/SearchDevices.d.ts.map +1 -1
  16. package/dist/api/allnetwork/AllNetworkGetAddress.d.ts +2 -0
  17. package/dist/api/allnetwork/AllNetworkGetAddress.d.ts.map +1 -1
  18. package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts +7 -1
  19. package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
  20. package/dist/api/allnetwork/AllNetworkGetAddressByLoop.d.ts.map +1 -1
  21. package/dist/api/device/DeviceVerify.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 +1 -0
  25. package/dist/core/index.d.ts.map +1 -1
  26. package/dist/data-manager/TransportManager.d.ts +2 -0
  27. package/dist/data-manager/TransportManager.d.ts.map +1 -1
  28. package/dist/device/Device.d.ts +2 -0
  29. package/dist/device/Device.d.ts.map +1 -1
  30. package/dist/index.d.ts +17 -19
  31. package/dist/index.js +449 -184
  32. package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
  33. package/dist/types/api/getFeatures.d.ts.map +1 -1
  34. package/dist/types/api/getPassphraseState.d.ts.map +1 -1
  35. package/dist/types/api/openWalletSession.d.ts +1 -10
  36. package/dist/types/api/openWalletSession.d.ts.map +1 -1
  37. package/dist/types/params.d.ts.map +1 -1
  38. package/dist/utils/patch.d.ts +1 -1
  39. package/dist/utils/patch.d.ts.map +1 -1
  40. package/package.json +4 -4
  41. package/src/api/GetFeatures.ts +1 -0
  42. package/src/api/GetPassphraseState.ts +1 -0
  43. package/src/api/OpenWalletSession.ts +7 -77
  44. package/src/api/SearchDevices.ts +121 -27
  45. package/src/api/allnetwork/AllNetworkGetAddress.ts +79 -45
  46. package/src/api/allnetwork/AllNetworkGetAddressBase.ts +95 -24
  47. package/src/api/allnetwork/AllNetworkGetAddressByLoop.ts +3 -0
  48. package/src/api/device/DeviceVerify.ts +8 -0
  49. package/src/core/RequestQueue.ts +20 -0
  50. package/src/core/index.ts +135 -43
  51. package/src/data/messages/messages-protocol-v2.json +21 -0
  52. package/src/data-manager/TransportManager.ts +14 -3
  53. package/src/device/Device.ts +58 -27
  54. package/src/protocols/protocol-v2/walletSession.ts +7 -0
  55. package/src/types/api/getFeatures.ts +2 -1
  56. package/src/types/api/getPassphraseState.ts +2 -5
  57. package/src/types/api/openWalletSession.ts +7 -19
  58. 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,
@@ -41858,6 +41878,7 @@ function getProtocolV2WalletSession(device, options) {
41858
41878
  ? device.getInternalState()
41859
41879
  : undefined;
41860
41880
  let response;
41881
+ let walletSelectionRequested = false;
41861
41882
  let resumed = false;
41862
41883
  let walletStatusRefreshed = false;
41863
41884
  const markWalletStatusRefreshed = () => {
@@ -42029,6 +42050,7 @@ function getProtocolV2WalletSession(device, options) {
42029
42050
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.WalletSessionInvalid);
42030
42051
  }
42031
42052
  yield lockAttachPinBeforePassphraseSelection();
42053
+ walletSelectionRequested = true;
42032
42054
  response = yield selectDeviceSession(device, expectedPassphraseState, options === null || options === void 0 ? void 0 : options.deriveCardano, markWalletStatusRefreshed);
42033
42055
  }
42034
42056
  let { message } = response;
@@ -42051,6 +42073,10 @@ function getProtocolV2WalletSession(device, options) {
42051
42073
  device.clearInternalState();
42052
42074
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.WalletSessionInvalid);
42053
42075
  }
42076
+ if (walletSelectionRequested) {
42077
+ clearCurrentWalletSession();
42078
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceCheckPassphraseStateError);
42079
+ }
42054
42080
  if (options === null || options === void 0 ? void 0 : options.onlyMainPin) {
42055
42081
  (_j = device.clearStandardInternalState) === null || _j === void 0 ? void 0 : _j.call(device);
42056
42082
  yield selectStandardWallet(true);
@@ -43679,6 +43705,18 @@ class TransportManager {
43679
43705
  this.defaultMessages = DataManager.getProtobufMessages();
43680
43706
  this.currentMessages = this.defaultMessages;
43681
43707
  this.protocolV1MessageSchema = 'v1CurrentSchema';
43708
+ this.webUsbInit = false;
43709
+ }
43710
+ static ensureInitialized() {
43711
+ return __awaiter(this, void 0, void 0, function* () {
43712
+ const env = DataManager.getSettings('env');
43713
+ if (env !== 'webusb' && env !== 'desktop-webusb')
43714
+ return;
43715
+ if (this.webUsbInit)
43716
+ return;
43717
+ yield this.transport.init(WebUsbLogger, DevicePool.emitter);
43718
+ this.webUsbInit = true;
43719
+ });
43682
43720
  }
43683
43721
  static configure() {
43684
43722
  return __awaiter(this, void 0, void 0, function* () {
@@ -43707,7 +43745,7 @@ class TransportManager {
43707
43745
  yield this.transport.init(WebBleLogger, DevicePool.emitter);
43708
43746
  }
43709
43747
  else if (env === 'webusb' || env === 'desktop-webusb') {
43710
- yield this.transport.init(WebUsbLogger, DevicePool.emitter);
43748
+ yield this.ensureInitialized();
43711
43749
  }
43712
43750
  else {
43713
43751
  yield this.transport.init(HttpLogger);
@@ -43790,6 +43828,7 @@ class TransportManager {
43790
43828
  }
43791
43829
  }
43792
43830
  TransportManager.reactNativeInit = false;
43831
+ TransportManager.webUsbInit = false;
43793
43832
  TransportManager.protocolV1MessageSchema = 'v1CurrentSchema';
43794
43833
  TransportManager.plugin = null;
43795
43834
 
@@ -46324,6 +46363,10 @@ class Device extends events.exports {
46324
46363
  }
46325
46364
  this.invalidateProtocolV2RuntimeState();
46326
46365
  }
46366
+ waitForRunCleanup() {
46367
+ var _a;
46368
+ return (_a = this.runCleanupPromise) !== null && _a !== void 0 ? _a : Promise.resolve();
46369
+ }
46327
46370
  run(fn, options) {
46328
46371
  return __awaiter(this, void 0, void 0, function* () {
46329
46372
  if (this.runPromise) {
@@ -46441,44 +46484,68 @@ class Device extends events.exports {
46441
46484
  });
46442
46485
  }
46443
46486
  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
- }));
46487
+ var _a;
46488
+ const attempt = this.connectionAttempt;
46489
+ if (((_a = this.userInterruption) === null || _a === void 0 ? void 0 : _a.attempt) === attempt) {
46490
+ return this.userInterruption.promise;
46491
+ }
46492
+ const error = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceInterruptedFromUser);
46493
+ this.interruptedAttempt = attempt;
46494
+ const cleanupPromise = this.runCleanupPromise;
46495
+ const { cancelableAction, commands, runPromise, deviceConnector, mainId } = this;
46496
+ const sendFallbackCancel = this.shouldSendFallbackProtocolCancel();
46497
+ const acquired = this.hasDeviceAcquire();
46498
+ const promise = (() => __awaiter(this, void 0, void 0, function* () {
46499
+ var _b;
46500
+ try {
46501
+ if (cancelableAction) {
46502
+ yield cancelableAction(error);
46503
+ }
46504
+ else if (sendFallbackCancel) {
46505
+ yield ((_b = commands === null || commands === void 0 ? void 0 : commands.cancelDevice) === null || _b === void 0 ? void 0 : _b.call(commands).catch(cancelError => {
46506
+ Log$h.debug('Protocol V2 fallback cancel error', cancelError);
46507
+ }));
46508
+ }
46509
+ else if (!acquired) {
46510
+ if (mainId && (deviceConnector === null || deviceConnector === void 0 ? void 0 : deviceConnector.disconnect)) {
46511
+ Log$h.debug('interruptionFromUser: disconnecting device without acquire, mainId:', mainId);
46512
+ yield deviceConnector.disconnect(mainId);
46513
+ }
46514
+ if (this.connectionAttempt === attempt)
46515
+ this.markTransportDisconnected();
46516
+ }
46517
+ yield (commands === null || commands === void 0 ? void 0 : commands.cancel());
46457
46518
  }
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);
46519
+ catch (cleanupError) {
46520
+ Log$h.warn('User cancellation cleanup failed; disconnecting device', cleanupError);
46521
+ if (mainId && (deviceConnector === null || deviceConnector === void 0 ? void 0 : deviceConnector.disconnect)) {
46522
+ yield deviceConnector.disconnect(mainId).catch(disconnectError => {
46523
+ Log$h.debug('User cancellation fallback disconnect failed', disconnectError);
46462
46524
  });
46463
46525
  }
46464
- this.markTransportDisconnected();
46526
+ if (this.connectionAttempt === attempt)
46527
+ this.markTransportDisconnected();
46465
46528
  }
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;
46529
+ finally {
46530
+ runPromise === null || runPromise === void 0 ? void 0 : runPromise.reject(error);
46531
+ if (this.runPromise === runPromise)
46532
+ this.runPromise = null;
46533
+ yield (cleanupPromise === null || cleanupPromise === void 0 ? void 0 : cleanupPromise.catch(() => undefined));
46470
46534
  }
46471
- yield (cleanupPromise === null || cleanupPromise === void 0 ? void 0 : cleanupPromise.catch(() => undefined));
46472
- });
46535
+ }))();
46536
+ this.userInterruption = { attempt, promise };
46537
+ return promise;
46473
46538
  }
46474
46539
  setCancelableAction(callback) {
46475
- this.cancelableAction = (e) => callback(e)
46540
+ const action = (e) => callback(e)
46476
46541
  .catch(e2 => {
46477
46542
  Log$h.debug('cancelableAction error', e2);
46478
46543
  })
46479
46544
  .finally(() => {
46480
- this.clearCancelableAction();
46545
+ if (this.cancelableAction === action)
46546
+ this.clearCancelableAction();
46481
46547
  });
46548
+ this.cancelableAction = action;
46482
46549
  }
46483
46550
  clearCancelableAction() {
46484
46551
  this.cancelableAction = undefined;
@@ -47210,6 +47277,48 @@ class PreInitialize extends BaseMethod {
47210
47277
  }
47211
47278
 
47212
47279
  const Log$e = getLogger(exports.LoggerNames.DevicePool);
47280
+ const getDescriptorKeys = (descriptor) => [descriptor.path, descriptor.id].filter((key) => typeof key === 'string' && key.length > 0);
47281
+ const isOwnedByActiveWebUsbRequest = (descriptor, requestQueue) => {
47282
+ if (!requestQueue)
47283
+ return false;
47284
+ return getDescriptorKeys(descriptor).some(key => requestQueue.getRequestTasksIdByConnectId(key).length > 0);
47285
+ };
47286
+ const getUsbHandle = (descriptor) => descriptor === null || descriptor === void 0 ? void 0 : descriptor.device;
47287
+ const getOwningRequestDevice = (descriptor, requestQueue) => {
47288
+ var _a, _b;
47289
+ if (!requestQueue)
47290
+ return undefined;
47291
+ const usbHandle = getUsbHandle(descriptor);
47292
+ if (usbHandle === undefined)
47293
+ return undefined;
47294
+ for (const key of getDescriptorKeys(descriptor)) {
47295
+ for (const requestId of requestQueue.getRequestTasksIdByConnectId(key)) {
47296
+ const device = (_a = requestQueue.getTask(requestId)) === null || _a === void 0 ? void 0 : _a.method.device;
47297
+ if ((device === null || device === void 0 ? void 0 : device.features) &&
47298
+ (device.mainId === key || ((_b = device.originalDescriptor) === null || _b === void 0 ? void 0 : _b.path) === key) &&
47299
+ getUsbHandle(device.originalDescriptor) === usbHandle) {
47300
+ return device;
47301
+ }
47302
+ }
47303
+ }
47304
+ return undefined;
47305
+ };
47306
+ const toSearchDeviceFromDescriptor = (descriptor) => {
47307
+ const connectId = descriptor.path || descriptor.id || null;
47308
+ return {
47309
+ connectId,
47310
+ uuid: '',
47311
+ serialNo: null,
47312
+ deviceId: null,
47313
+ deviceType: hdShared.EDeviceType.Unknown,
47314
+ name: descriptor.name || connectId || '',
47315
+ commType: descriptor.commType,
47316
+ };
47317
+ };
47318
+ const toSearchDevice = (device) => {
47319
+ const message = device.toMessageObject();
47320
+ return message ? message : null;
47321
+ };
47213
47322
  class SearchDevices extends BaseMethod {
47214
47323
  init() {
47215
47324
  this.useDevice = false;
@@ -47217,20 +47326,32 @@ class SearchDevices extends BaseMethod {
47217
47326
  this.skipForceUpdateCheck = true;
47218
47327
  }
47219
47328
  run() {
47220
- var _a, _b, _c, _d, _e;
47329
+ var _a, _b, _c, _d, _e, _f, _g;
47221
47330
  return __awaiter(this, void 0, void 0, function* () {
47222
- yield TransportManager.configure();
47223
- const deviceDiff = yield ((_a = this.connector) === null || _a === void 0 ? void 0 : _a.enumerate());
47224
- const devicesDescriptor = (_b = deviceDiff === null || deviceDiff === void 0 ? void 0 : deviceDiff.descriptors) !== null && _b !== void 0 ? _b : [];
47225
47331
  const env = DataManager.getSettings('env');
47332
+ const isWebUsb = env === 'webusb' || env === 'desktop-webusb';
47333
+ const requestQueue = (_a = this.context) === null || _a === void 0 ? void 0 : _a.requestQueue;
47334
+ const hasActiveWebUsbRequest = isWebUsb && ((_b = requestQueue === null || requestQueue === void 0 ? void 0 : requestQueue.getRequestTasksId().length) !== null && _b !== void 0 ? _b : 0) > 0;
47335
+ if (isWebUsb) {
47336
+ try {
47337
+ yield TransportManager.ensureInitialized();
47338
+ }
47339
+ catch (error) {
47340
+ Log$e.debug('WebUSB bring-up unavailable', error);
47341
+ }
47342
+ }
47343
+ if (!hasActiveWebUsbRequest)
47344
+ yield TransportManager.configure();
47345
+ const deviceDiff = yield ((_c = this.connector) === null || _c === void 0 ? void 0 : _c.enumerate());
47346
+ const devicesDescriptor = (_d = deviceDiff === null || deviceDiff === void 0 ? void 0 : deviceDiff.descriptors) !== null && _d !== void 0 ? _d : [];
47226
47347
  if (DataManager.isBleConnect(env)) {
47227
47348
  const devices = [];
47228
47349
  const seenIds = new Set();
47229
47350
  for (const device of devicesDescriptor) {
47230
- const lowerId = (_c = device.id) === null || _c === void 0 ? void 0 : _c.toLowerCase();
47351
+ const lowerId = (_e = device.id) === null || _e === void 0 ? void 0 : _e.toLowerCase();
47231
47352
  if (!seenIds.has(lowerId)) {
47232
47353
  seenIds.add(lowerId);
47233
- const rawBleName = (_e = (_d = device.name) !== null && _d !== void 0 ? _d : device.localName) !== null && _e !== void 0 ? _e : '';
47354
+ const rawBleName = (_g = (_f = device.name) !== null && _f !== void 0 ? _f : device.localName) !== null && _g !== void 0 ? _g : '';
47234
47355
  const bleName = hdShared.canonicalizePro2BleAdvertisementName(rawBleName);
47235
47356
  devices.push(Object.assign(Object.assign({}, device), { connectId: device.id, serialNo: null, uuid: '', deviceId: null, name: bleName || device.name, deviceType: getDeviceTypeByBleName(bleName) }));
47236
47357
  }
@@ -47239,22 +47360,34 @@ class SearchDevices extends BaseMethod {
47239
47360
  }
47240
47361
  const deviceList = [];
47241
47362
  for (const descriptor of devicesDescriptor) {
47242
- try {
47243
- const result = yield DevicePool.getDevices([descriptor], descriptor.path, {
47244
- connectProtocol: undefined,
47245
- forceProtocolDetection: true,
47246
- refreshRuntimeState: true,
47247
- });
47248
- deviceList.push(...result.deviceList);
47363
+ if (hasActiveWebUsbRequest && isOwnedByActiveWebUsbRequest(descriptor, requestQueue)) {
47364
+ const cached = DevicePool.getDeviceByPath(descriptor.path);
47365
+ const known = (cached === null || cached === void 0 ? void 0 : cached.features) ? cached : getOwningRequestDevice(descriptor, requestQueue);
47366
+ const message = known ? toSearchDevice(known) : null;
47367
+ deviceList.push(message !== null && message !== void 0 ? message : toSearchDeviceFromDescriptor(descriptor));
47249
47368
  }
47250
- catch (error) {
47251
- const errorCode = error && typeof error === 'object' && 'errorCode' in error
47252
- ? error.errorCode
47253
- : undefined;
47254
- Log$e.debug('Skip unavailable device during search', Object.assign({ path: descriptor.path }, (errorCode !== undefined ? { errorCode } : {})));
47369
+ else {
47370
+ try {
47371
+ const result = yield DevicePool.getDevices([descriptor], descriptor.path, {
47372
+ connectProtocol: undefined,
47373
+ forceProtocolDetection: true,
47374
+ refreshRuntimeState: true,
47375
+ });
47376
+ for (const device of result.deviceList) {
47377
+ const message = toSearchDevice(device);
47378
+ if (message)
47379
+ deviceList.push(message);
47380
+ }
47381
+ }
47382
+ catch (error) {
47383
+ const errorCode = error && typeof error === 'object' && 'errorCode' in error
47384
+ ? error.errorCode
47385
+ : undefined;
47386
+ Log$e.debug('Skip unavailable device during search', Object.assign({ path: descriptor.path }, (errorCode !== undefined ? { errorCode } : {})));
47387
+ }
47255
47388
  }
47256
47389
  }
47257
- return deviceList.map(device => device.toMessageObject());
47390
+ return deviceList;
47258
47391
  });
47259
47392
  }
47260
47393
  }
@@ -47588,15 +47721,6 @@ function validateResult(result, nonNullableFields, options) {
47588
47721
  }
47589
47722
  }
47590
47723
 
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
47724
  const wasResumed = (session) => !!session &&
47601
47725
  typeof session === 'object' &&
47602
47726
  'resumed' in session &&
@@ -47618,25 +47742,16 @@ const normalizeParams = (payload) => {
47618
47742
  throw invalidParameter('Parameter [mode] is required.');
47619
47743
  }
47620
47744
  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.');
47745
+ payload.mode !== OpenWalletSessionMode.SelectHidden) {
47746
+ throw invalidParameter('Parameter [mode] must be one of standard or select-hidden.');
47624
47747
  }
47625
47748
  if (payload.useEmptyPassphrase !== undefined || payload.initSession !== undefined) {
47626
47749
  throw invalidParameter('Legacy parameters [useEmptyPassphrase] and [initSession] are not supported by openWalletSession.');
47627
47750
  }
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 };
47751
+ if (payload.deviceId !== undefined || payload.passphraseState !== undefined) {
47752
+ throw invalidParameter('Parameters [deviceId] and [passphraseState] are not supported by openWalletSession. Pass passphraseState on later address and signing calls.');
47634
47753
  }
47635
- return {
47636
- mode: OpenWalletSessionMode.ResumeHidden,
47637
- deviceId: requiredString(payload.deviceId, 'deviceId'),
47638
- passphraseState: requiredString(payload.passphraseState, 'passphraseState'),
47639
- };
47754
+ return { mode: payload.mode };
47640
47755
  };
47641
47756
  class OpenWalletSession extends BaseMethod {
47642
47757
  getSupportedProtocols() {
@@ -47739,43 +47854,6 @@ class OpenWalletSession extends BaseMethod {
47739
47854
  resumed: wasResumed(session),
47740
47855
  };
47741
47856
  }
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
47857
  this.device.passphraseState = undefined;
47780
47858
  const walletStatus = yield ensureProtocolV2WalletStatus();
47781
47859
  if (isProtocolV2 && walletStatus.status.passphraseProtection !== true) {
@@ -49186,6 +49264,14 @@ class DeviceVerify extends BaseMethod {
49186
49264
  this.unlockPolicy = 'unlock-before-run';
49187
49265
  this.protocolV2PreUnlockPinType = hdTransport.DeviceSessionPinType.Any;
49188
49266
  this.useDevicePassphraseState = false;
49267
+ this.protocolV2UiInteraction = {
49268
+ request: 'button',
49269
+ source: 'method-lifecycle',
49270
+ reason: 'device-management',
49271
+ completion: 'operation-completed',
49272
+ deviceOnly: true,
49273
+ operation: 'deviceVerify',
49274
+ };
49189
49275
  validateParams(this.payload, [{ name: 'dataHex', type: 'hexString' }]);
49190
49276
  this.params = {
49191
49277
  data: formatAnyHex(this.payload.dataHex),
@@ -55908,6 +55994,8 @@ class AllNetworkGetAddressBase extends BaseMethod {
55908
55994
  constructor() {
55909
55995
  super(...arguments);
55910
55996
  this.abortController = null;
55997
+ this.loadingCleanupInBackground = false;
55998
+ this.protocolV2ResumedSeedDomains = new Set();
55911
55999
  }
55912
56000
  getSupportedProtocols() {
55913
56001
  return ['V1', 'V2'];
@@ -55943,7 +56031,20 @@ class AllNetworkGetAddressBase extends BaseMethod {
55943
56031
  _originalIndex: originalIndex,
55944
56032
  };
55945
56033
  }
55946
- callMethod(methodName, params, rootFingerprint) {
56034
+ hasProtocolV2WalletResume(deriveCardano) {
56035
+ if (deriveCardano) {
56036
+ return this.protocolV2ResumedSeedDomains.has('cardano');
56037
+ }
56038
+ return (this.protocolV2ResumedSeedDomains.has('standard') ||
56039
+ this.protocolV2ResumedSeedDomains.has('cardano'));
56040
+ }
56041
+ markProtocolV2WalletResumed(deriveCardano) {
56042
+ this.protocolV2ResumedSeedDomains.add('standard');
56043
+ if (deriveCardano) {
56044
+ this.protocolV2ResumedSeedDomains.add('cardano');
56045
+ }
56046
+ }
56047
+ callMethod(methodName, params, rootFingerprint, postMessage = this.postMessage) {
55947
56048
  var _a, _b, _c;
55948
56049
  return __awaiter(this, void 0, void 0, function* () {
55949
56050
  const method = findMethod({
@@ -55952,7 +56053,7 @@ class AllNetworkGetAddressBase extends BaseMethod {
55952
56053
  payload: Object.assign({ connectId: this.payload.connectId, deviceId: this.payload.deviceId, method: methodName }, params),
55953
56054
  });
55954
56055
  method.connector = this.connector;
55955
- method.postMessage = this.postMessage;
56056
+ method.postMessage = postMessage;
55956
56057
  if (this.context) {
55957
56058
  (_a = method.setContext) === null || _a === void 0 ? void 0 : _a.call(method, this.context);
55958
56059
  }
@@ -56005,11 +56106,14 @@ class AllNetworkGetAddressBase extends BaseMethod {
56005
56106
  const useEmptyPassphrase = this.payload.useEmptyPassphrase === true;
56006
56107
  const deriveCardano = method.name.startsWith('cardano') ? true : undefined;
56007
56108
  const shouldResumeWalletSession = useEmptyPassphrase || !!this.payload.passphraseState;
56008
- if (this.device.isProtocolV2() && shouldResumeWalletSession) {
56109
+ if (this.device.isProtocolV2() &&
56110
+ shouldResumeWalletSession &&
56111
+ !this.hasProtocolV2WalletResume(deriveCardano)) {
56009
56112
  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);
56010
56113
  if (!passphraseStateSafety) {
56011
56114
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceCheckPassphraseStateError);
56012
56115
  }
56116
+ this.markProtocolV2WalletResumed(deriveCardano);
56013
56117
  }
56014
56118
  }),
56015
56119
  });
@@ -56045,27 +56149,63 @@ class AllNetworkGetAddressBase extends BaseMethod {
56045
56149
  return result;
56046
56150
  });
56047
56151
  }
56048
- run() {
56152
+ stopAllNetworkLoading(canSend = true) {
56049
56153
  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));
56154
+ const commands = this.loadingCommands;
56155
+ this.loadingCommands = undefined;
56156
+ if (!canSend || !commands || commands.disposed || commands !== this.device.commands)
56157
+ return;
56158
+ try {
56159
+ yield commands.typedCall('DeviceAnimationControl', 'Success', {
56160
+ action: hdTransport.Messages.DeviceAnimationAction.AnimationAction_Stop,
56161
+ });
56058
56162
  }
56059
- if (res.message.root_fingerprint == null) {
56060
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallMethodInvalidParameter);
56163
+ catch (_a) {
56061
56164
  }
56062
- this.abortController = new AbortController();
56063
- return this.getAllNetworkAddress(res.message.root_fingerprint).catch(e => {
56165
+ });
56166
+ }
56167
+ run() {
56168
+ return __awaiter(this, void 0, void 0, function* () {
56169
+ this.loadingCleanupInBackground = false;
56170
+ try {
56171
+ if (this.device.isProtocolV2() &&
56172
+ (this.device.getCurrentDeviceType() === hdShared.EDeviceType.Pro2 ||
56173
+ this.device.getCurrentDeviceType() === hdShared.EDeviceType.Neo)) {
56174
+ const protocolInfo = yield this.device.ensureProtocolV2RuntimeContext();
56175
+ if (supportsProtocolV2Message(protocolInfo, 60461)) {
56176
+ const { commands } = this.device;
56177
+ yield commands.typedCall('DeviceAnimationControl', 'Success', {
56178
+ action: hdTransport.Messages.DeviceAnimationAction.AnimationAction_Start,
56179
+ });
56180
+ this.loadingCommands = commands;
56181
+ }
56182
+ }
56183
+ const res = yield this.device.commands.typedCall('GetPublicKey', 'PublicKey', {
56184
+ address_n: [toHardened(44), toHardened(1), toHardened(0)],
56185
+ coin_name: 'Testnet',
56186
+ script_type: 'SPENDADDRESS',
56187
+ show_display: false,
56188
+ });
56189
+ if (!this.device.isProtocolV2()) {
56190
+ this.postMessage(createUiMessage(UI_REQUEST.CLOSE_UI_PIN_WINDOW));
56191
+ }
56192
+ if (res.message.root_fingerprint == null) {
56193
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallMethodInvalidParameter);
56194
+ }
56195
+ this.abortController = new AbortController();
56196
+ return yield this.getAllNetworkAddress(res.message.root_fingerprint);
56197
+ }
56198
+ catch (e) {
56199
+ yield this.stopAllNetworkLoading(false);
56064
56200
  if (e instanceof hdShared.HardwareError && e.errorCode === hdShared.HardwareErrorCode.RepeatUnlocking) {
56065
56201
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RepeatUnlocking, e.message);
56066
56202
  }
56067
56203
  throw e;
56068
- });
56204
+ }
56205
+ finally {
56206
+ if (!this.loadingCleanupInBackground)
56207
+ yield this.stopAllNetworkLoading();
56208
+ }
56069
56209
  });
56070
56210
  }
56071
56211
  }
@@ -56126,57 +56266,83 @@ function handleSkippableHardwareError(e, device, method) {
56126
56266
  }
56127
56267
 
56128
56268
  class AllNetworkGetAddress extends AllNetworkGetAddressBase {
56269
+ checkAborted() {
56270
+ var _a;
56271
+ if ((_a = this.abortController) === null || _a === void 0 ? void 0 : _a.signal.aborted) {
56272
+ throw new Error(hdShared.HardwareErrorCodeMessage[hdShared.HardwareErrorCode.RepeatUnlocking]);
56273
+ }
56274
+ }
56275
+ callAddressGroup(methodName, params, rootFingerprint) {
56276
+ return __awaiter(this, void 0, void 0, function* () {
56277
+ const methodCallParams = { bundle: params.map(param => (Object.assign({}, param.params))) };
56278
+ if (!this.device.isProtocolV2() || params.length === 1) {
56279
+ return this.callMethod(methodName, methodCallParams, rootFingerprint);
56280
+ }
56281
+ const postedAddressCounts = new Map();
56282
+ let runningIndividually = false;
56283
+ const postMessage = message => {
56284
+ var _a;
56285
+ if (message.type === UI_REQUEST.PREVIOUS_ADDRESS_RESULT) {
56286
+ const { path, address } = message.payload.data;
56287
+ const key = JSON.stringify([path, address]);
56288
+ const count = (_a = postedAddressCounts.get(key)) !== null && _a !== void 0 ? _a : 0;
56289
+ if (runningIndividually && count > 0) {
56290
+ postedAddressCounts.set(key, count - 1);
56291
+ return;
56292
+ }
56293
+ if (!runningIndividually)
56294
+ postedAddressCounts.set(key, count + 1);
56295
+ }
56296
+ this.postMessage(message);
56297
+ };
56298
+ if (params.every(param => param._originRequestParams.showOnOneKey === false)) {
56299
+ const response = yield this.callMethod(methodName, methodCallParams, rootFingerprint, postMessage);
56300
+ if (response.some(item => item.success))
56301
+ return response;
56302
+ }
56303
+ runningIndividually = true;
56304
+ const responses = [];
56305
+ for (const param of params) {
56306
+ this.checkAborted();
56307
+ const response = yield this.callMethod(methodName, { bundle: [Object.assign({}, param.params)] }, rootFingerprint, postMessage);
56308
+ responses.push(...response);
56309
+ }
56310
+ return responses;
56311
+ });
56312
+ }
56129
56313
  getAllNetworkAddress(rootFingerprint) {
56130
- var _a, _b, _c, _d;
56131
56314
  return __awaiter(this, void 0, void 0, function* () {
56132
56315
  const responses = [];
56133
- const resultMap = {};
56134
56316
  const { bundle } = this.payload;
56135
56317
  const methodParams = bundle.map((param, index) => this.generateMethodName({
56136
56318
  network: param.network,
56137
56319
  payload: param,
56138
56320
  originalIndex: index,
56139
56321
  }));
56140
- const groupedMethodParams = methodParams.reduce((groups, param) => {
56322
+ const methodGroups = methodParams.reduce((groups, param) => {
56141
56323
  var _a;
56142
56324
  const group = (_a = groups.get(param.methodName)) !== null && _a !== void 0 ? _a : [];
56143
56325
  group.push(param);
56144
56326
  groups.set(param.methodName, group);
56145
56327
  return groups;
56146
56328
  }, new Map());
56147
- const requiresProtocolV2WalletHandoff = this.device.isProtocolV2() &&
56148
- (this.payload.useEmptyPassphrase === true || !!this.payload.passphraseState);
56149
- const methodGroups = requiresProtocolV2WalletHandoff
56150
- ? methodParams.map(param => [param.methodName, [param]])
56151
- : Array.from(groupedMethodParams.entries());
56152
- let i = 0;
56153
- for (const [methodName, params] of methodGroups) {
56154
- const methodParams = {
56155
- bundle: params.map(param => (Object.assign({}, param.params))),
56156
- };
56157
- if ((_a = this.abortController) === null || _a === void 0 ? void 0 : _a.signal.aborted) {
56158
- throw new Error(hdShared.HardwareErrorCodeMessage[hdShared.HardwareErrorCode.RepeatUnlocking]);
56159
- }
56160
- const response = yield this.callMethod(methodName, methodParams, rootFingerprint);
56161
- if ((_b = this.abortController) === null || _b === void 0 ? void 0 : _b.signal.aborted) {
56162
- throw new Error(hdShared.HardwareErrorCodeMessage[hdShared.HardwareErrorCode.RepeatUnlocking]);
56163
- }
56164
- for (let i = 0; i < params.length; i++) {
56165
- const { _originRequestParams, _originalIndex } = params[i];
56166
- const responseKey = `${_originalIndex}`;
56167
- resultMap[responseKey] = Object.assign(Object.assign({}, _originRequestParams), response[i]);
56329
+ let processed = 0;
56330
+ for (const [methodName, params] of methodGroups.entries()) {
56331
+ this.checkAborted();
56332
+ const response = yield this.callAddressGroup(methodName, params, rootFingerprint);
56333
+ this.checkAborted();
56334
+ for (let index = 0; index < params.length; index++) {
56335
+ const { _originRequestParams, _originalIndex } = params[index];
56336
+ responses[_originalIndex] = Object.assign(Object.assign({}, _originRequestParams), response[index]);
56168
56337
  }
56169
- if (((_d = (_c = this.payload) === null || _c === void 0 ? void 0 : _c.bundle) === null || _d === void 0 ? void 0 : _d.length) > 1) {
56170
- const progress = Math.round(((i + 1) / this.payload.bundle.length) * 100);
56338
+ processed += params.length;
56339
+ if (bundle.length > 1) {
56340
+ const progress = Math.round((processed / bundle.length) * 100);
56171
56341
  this.postMessage(createUiMessage(UI_REQUEST.DEVICE_PROGRESS, { progress }));
56172
56342
  }
56173
- i++;
56174
- }
56175
- for (let i = 0; i < bundle.length; i++) {
56176
- responses.push(resultMap[i]);
56177
56343
  }
56178
56344
  this.abortController = null;
56179
- return Promise.resolve(responses);
56345
+ return responses;
56180
56346
  });
56181
56347
  }
56182
56348
  }
@@ -56192,6 +56358,7 @@ class AllNetworkGetAddressByLoop extends AllNetworkGetAddressBase {
56192
56358
  throw new Error('callbackIdFinish is required');
56193
56359
  }
56194
56360
  const bundle = this.payload.bundle || [this.payload];
56361
+ this.loadingCleanupInBackground = true;
56195
56362
  const callbackPromise = this.processCallbacksInBackground(bundle, rootFingerprint, callbackId, callbackIdFinish);
56196
56363
  this.device.pendingCallbackPromise = hdShared.createDeferred(callbackPromise);
56197
56364
  if (this.context && this.payload.connectId) {
@@ -56232,6 +56399,7 @@ class AllNetworkGetAddressByLoop extends AllNetworkGetAddressBase {
56232
56399
  });
56233
56400
  }
56234
56401
  catch (error) {
56402
+ yield this.stopAllNetworkLoading(false);
56235
56403
  let errorCode = error.errorCode || error.code;
56236
56404
  let errorMessage = error.message;
56237
56405
  if (error instanceof hdShared.HardwareError) {
@@ -56259,6 +56427,7 @@ class AllNetworkGetAddressByLoop extends AllNetworkGetAddressBase {
56259
56427
  });
56260
56428
  }
56261
56429
  finally {
56430
+ yield this.stopAllNetworkLoading();
56262
56431
  (_c = this.context) === null || _c === void 0 ? void 0 : _c.cancelCallbackTasks(this.payload.connectId);
56263
56432
  this.abortController = null;
56264
56433
  }
@@ -65584,6 +65753,29 @@ class RequestQueue {
65584
65753
  getTask(requestId) {
65585
65754
  return this.requestQueue.get(requestId);
65586
65755
  }
65756
+ waitForTask(task, pending) {
65757
+ return __awaiter(this, void 0, void 0, function* () {
65758
+ const signal = task.method.abortSignal;
65759
+ const cancellationError = () => hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallQueueActionCancelled);
65760
+ if (signal === null || signal === void 0 ? void 0 : signal.aborted)
65761
+ throw cancellationError();
65762
+ let onAbort;
65763
+ try {
65764
+ const cancelled = new Promise((_, reject) => {
65765
+ onAbort = () => reject(cancellationError());
65766
+ signal === null || signal === void 0 ? void 0 : signal.addEventListener('abort', onAbort, { once: true });
65767
+ });
65768
+ const result = yield Promise.race([pending(), cancelled]);
65769
+ if (signal === null || signal === void 0 ? void 0 : signal.aborted)
65770
+ throw cancellationError();
65771
+ return result;
65772
+ }
65773
+ finally {
65774
+ if (onAbort)
65775
+ signal === null || signal === void 0 ? void 0 : signal.removeEventListener('abort', onAbort);
65776
+ }
65777
+ });
65778
+ }
65587
65779
  getAbortController(requestId) {
65588
65780
  var _a;
65589
65781
  return (_a = this.requestQueue.get(requestId)) === null || _a === void 0 ? void 0 : _a.abortController;
@@ -65783,7 +65975,8 @@ const createUiProgressMessageFilter = (intervalMs = DEFAULT_UI_PROGRESS_INTERVAL
65783
65975
 
65784
65976
  const Log = getLogger(exports.LoggerNames.Core);
65785
65977
  const PRE_INITIALIZE_TTL_MS = 60 * 1000;
65786
- const PRE_PENDING_CALL_TIMEOUT_MS = 15 * 1000;
65978
+ const PRE_PENDING_CALL_TIMEOUT_MS = 5 * 1000;
65979
+ const PRO2_USB_SIGNING_COOLDOWN_MS = 1000;
65787
65980
  const preWarmInflight = new Map();
65788
65981
  const preWarmDoneAt = new Map();
65789
65982
  function resolveDeriveCardano(method) {
@@ -65862,6 +66055,7 @@ const callAPI = (context, message) => __awaiter(void 0, void 0, void 0, function
65862
66055
  }
65863
66056
  };
65864
66057
  (_a = method.setContext) === null || _a === void 0 ? void 0 : _a.call(method, context);
66058
+ method.context = context;
65865
66059
  method.requestContext = createRequestContext(method.responseID, method.name, {
65866
66060
  sdkInstanceId: context.sdkInstanceId,
65867
66061
  connectId: method.connectId,
@@ -65879,7 +66073,11 @@ const callAPI = (context, message) => __awaiter(void 0, void 0, void 0, function
65879
66073
  if (!method.useDevice) {
65880
66074
  updateMethodRequestContext(method, { status: 'running' });
65881
66075
  try {
65882
- const response = yield method.run();
66076
+ const env = DataManager.getSettings('env');
66077
+ const response = method.name === 'searchDevices' &&
66078
+ (DataManager.isBrowserWebUsb(env) || DataManager.isDesktopWebUsb(env))
66079
+ ? yield context.methodSynchronize(() => method.run(), 'webusb-discovery')
66080
+ : yield method.run();
65883
66081
  completeMethodRequestContext(method);
65884
66082
  return createResponseMessage(method.responseID, true, response);
65885
66083
  }
@@ -65951,6 +66149,7 @@ const waitForPendingPromise = (connectId, getPrePendingCallPromise, removePrePen
65951
66149
  Log.debug('pre pending call promise before call method, wait for it');
65952
66150
  let timer;
65953
66151
  let timedOut = false;
66152
+ let completed = false;
65954
66153
  try {
65955
66154
  yield Promise.race([
65956
66155
  pendingPromise,
@@ -65961,13 +66160,13 @@ const waitForPendingPromise = (connectId, getPrePendingCallPromise, removePrePen
65961
66160
  }, PRE_PENDING_CALL_TIMEOUT_MS);
65962
66161
  }),
65963
66162
  ]);
65964
- }
65965
- catch (error) {
66163
+ completed = !timedOut;
65966
66164
  }
65967
66165
  finally {
65968
66166
  if (timer)
65969
66167
  clearTimeout(timer);
65970
- removePrePendingCallPromise === null || removePrePendingCallPromise === void 0 ? void 0 : removePrePendingCallPromise(connectId, pendingPromise);
66168
+ if (timedOut || completed)
66169
+ removePrePendingCallPromise === null || removePrePendingCallPromise === void 0 ? void 0 : removePrePendingCallPromise(connectId, pendingPromise);
65971
66170
  }
65972
66171
  if (timedOut) {
65973
66172
  Log.warn('pre pending call promise timed out before call method', { connectId });
@@ -65975,8 +66174,19 @@ const waitForPendingPromise = (connectId, getPrePendingCallPromise, removePrePen
65975
66174
  Log.debug('pre pending call promise before call method done');
65976
66175
  }
65977
66176
  });
66177
+ function getPostCallPendingPromise(method, device) {
66178
+ const cleanupPromise = device.waitForRunCleanup();
66179
+ const env = DataManager.getSettings('env');
66180
+ const deviceType = device.getCurrentDeviceType();
66181
+ const requiresSigningCooldown = method.name.includes('Sign') &&
66182
+ (deviceType === hdShared.EDeviceType.Pro2 || deviceType === hdShared.EDeviceType.Neo) &&
66183
+ (DataManager.isBrowserWebUsb(env) || DataManager.isDesktopWebUsb(env) || env === 'node-usb');
66184
+ return requiresSigningCooldown
66185
+ ? cleanupPromise.then(() => wait(PRO2_USB_SIGNING_COOLDOWN_MS)).then(() => undefined)
66186
+ : cleanupPromise;
66187
+ }
65978
66188
  const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, void 0, function* () {
65979
- var _d, _e, _f, _g, _h, _j, _k;
66189
+ var _d, _e, _f, _g, _h, _j;
65980
66190
  let messageResponse;
65981
66191
  const { requestQueue, getPrePendingCallPromise, removePrePendingCallPromise } = context;
65982
66192
  updateMethodRequestContext(method, { status: 'running' });
@@ -65990,21 +66200,42 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
65990
66200
  Log.debug('passphrase state change, clear device cache');
65991
66201
  DevicePool.clearDeviceCache(method.payload.connectId);
65992
66202
  }
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
66203
  const task = requestQueue.createTask(method);
65998
66204
  let preWarmCallbackTask;
65999
- if (method.isPreWarmSignal && method.connectId) {
66000
- preWarmCallbackTask = hdShared.createDeferred();
66001
- context.registerCallbackTask(method.connectId, preWarmCallbackTask);
66002
- }
66003
66205
  let device;
66004
66206
  try {
66005
- const connectId = (_e = method.connectId) !== null && _e !== void 0 ? _e : '';
66207
+ const connectId = (_d = method.connectId) !== null && _d !== void 0 ? _d : '';
66208
+ if (connectId) {
66209
+ yield requestQueue.waitForTask(task, () => context.waitForCallbackTasks(connectId));
66210
+ }
66211
+ yield requestQueue.waitForTask(task, () => {
66212
+ var _a;
66213
+ return waitForPendingPromise((_a = method.connectId) !== null && _a !== void 0 ? _a : '', getPrePendingCallPromise, removePrePendingCallPromise);
66214
+ });
66215
+ if (method.isPreWarmSignal && method.connectId) {
66216
+ preWarmCallbackTask = hdShared.createDeferred();
66217
+ context.registerCallbackTask(method.connectId, preWarmCallbackTask);
66218
+ }
66006
66219
  const pollingId = pollingManager.start(connectId);
66007
- device = yield ensureConnected(context, method, connectId, pollingId, (_f = task.abortController) === null || _f === void 0 ? void 0 : _f.signal);
66220
+ const env = DataManager.getSettings('env');
66221
+ const connect = () => ensureConnected(context, method, connectId, pollingId, method.abortSignal);
66222
+ if (DataManager.isBrowserWebUsb(env) || DataManager.isDesktopWebUsb(env)) {
66223
+ const connectPromise = context.methodSynchronize(() => __awaiter(void 0, void 0, void 0, function* () {
66224
+ var _k;
66225
+ if ((_k = method.abortSignal) === null || _k === void 0 ? void 0 : _k.aborted) {
66226
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallQueueActionCancelled);
66227
+ }
66228
+ return connect();
66229
+ }), 'webusb-discovery');
66230
+ connectPromise.catch(() => undefined);
66231
+ device = yield requestQueue.waitForTask(task, () => connectPromise);
66232
+ }
66233
+ else {
66234
+ device = yield connect();
66235
+ }
66236
+ if ((_e = method.abortSignal) === null || _e === void 0 ? void 0 : _e.aborted) {
66237
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallQueueActionCancelled);
66238
+ }
66008
66239
  }
66009
66240
  catch (e) {
66010
66241
  preWarmCallbackTask === null || preWarmCallbackTask === void 0 ? void 0 : preWarmCallbackTask.resolve();
@@ -66019,7 +66250,7 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
66019
66250
  requestQueue.releaseTask(method.responseID);
66020
66251
  return createResponseMessage(method.responseID, false, { error: e });
66021
66252
  }
66022
- if ((_g = method.payload) === null || _g === void 0 ? void 0 : _g.onlyConnectBleDevice) {
66253
+ if ((_f = method.payload) === null || _f === void 0 ? void 0 : _f.onlyConnectBleDevice) {
66023
66254
  preWarmCallbackTask === null || preWarmCallbackTask === void 0 ? void 0 : preWarmCallbackTask.resolve();
66024
66255
  Log.debug('Call API - only connect ble device: ', device === null || device === void 0 ? void 0 : device.mainId);
66025
66256
  completeMethodRequestContext(method);
@@ -66027,11 +66258,11 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
66027
66258
  return createResponseMessage(method.responseID, true, null);
66028
66259
  }
66029
66260
  Log.debug('Call API - setDevice: ', device.mainId);
66030
- (_h = method.setDevice) === null || _h === void 0 ? void 0 : _h.call(method, device);
66261
+ (_g = method.setDevice) === null || _g === void 0 ? void 0 : _g.call(method, device);
66031
66262
  method.context = context;
66032
66263
  updateMethodRequestContext(method, {
66033
66264
  deviceInstanceId: device.instanceId,
66034
- commandsInstanceId: (_j = device.commands) === null || _j === void 0 ? void 0 : _j.instanceId,
66265
+ commandsInstanceId: (_h = device.commands) === null || _h === void 0 ? void 0 : _h.instanceId,
66035
66266
  });
66036
66267
  const activeRequests = getActiveRequestsByDeviceInstance(device.instanceId);
66037
66268
  if (activeRequests.length > 0) {
@@ -66057,10 +66288,14 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
66057
66288
  device.beginProtocolV2UiInteraction();
66058
66289
  device.on(DEVICE.SELECT_DEVICE_FOR_SWITCH_FIRMWARE_WEB_DEVICE, onSelectDeviceForSwitchFirmwareWebDeviceHandler);
66059
66290
  try {
66060
- if (method.connectId) {
66061
- yield context.waitForCallbackTasks(method.connectId, preWarmCallbackTask);
66291
+ const { connectId } = method;
66292
+ if (connectId) {
66293
+ yield requestQueue.waitForTask(task, () => context.waitForCallbackTasks(connectId, preWarmCallbackTask));
66062
66294
  }
66063
- yield waitForPendingPromise((_k = method.connectId) !== null && _k !== void 0 ? _k : '', getPrePendingCallPromise, removePrePendingCallPromise);
66295
+ yield requestQueue.waitForTask(task, () => {
66296
+ var _a;
66297
+ return waitForPendingPromise((_a = method.connectId) !== null && _a !== void 0 ? _a : '', getPrePendingCallPromise, removePrePendingCallPromise);
66298
+ });
66064
66299
  const inner = () => __awaiter(void 0, void 0, void 0, function* () {
66065
66300
  var _l, _m;
66066
66301
  method.assertProtocolSupported(device.getProtocol(), device.getCurrentFirmwareType());
@@ -66187,6 +66422,9 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
66187
66422
  }),
66188
66423
  });
66189
66424
  messageResponse = createResponseMessage(method.responseID, true, response);
66425
+ if (method.connectId) {
66426
+ context.setPrePendingCallPromise(method.connectId, getPostCallPendingPromise(method, device));
66427
+ }
66190
66428
  requestQueue.resolveRequest(method.responseID, messageResponse);
66191
66429
  completeMethodRequestContext(method);
66192
66430
  }
@@ -66197,6 +66435,9 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
66197
66435
  }
66198
66436
  Log.debug(`Call API - Inner Method Run Error`, error);
66199
66437
  messageResponse = createResponseMessage(method.responseID, false, { error });
66438
+ if (method.connectId) {
66439
+ context.setPrePendingCallPromise(method.connectId, getPostCallPendingPromise(method, device));
66440
+ }
66200
66441
  requestQueue.resolveRequest(method.responseID, messageResponse);
66201
66442
  completeMethodRequestContext(method, error);
66202
66443
  if (error instanceof hdShared.HardwareError &&
@@ -66215,6 +66456,9 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
66215
66456
  });
66216
66457
  Log.debug('Call API - Device Run: ', device.mainId);
66217
66458
  const runOptions = Object.assign({ keepSession: method.payload.keepSession, skipInitialize: canSkipInitialize(method, device) }, parseInitOptions(method));
66459
+ if ((_j = method.abortSignal) === null || _j === void 0 ? void 0 : _j.aborted) {
66460
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallQueueActionCancelled);
66461
+ }
66218
66462
  const deviceRun = () => device.run(inner, runOptions);
66219
66463
  task.callPromise = hdShared.createDeferred(deviceRun);
66220
66464
  try {
@@ -66233,6 +66477,7 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
66233
66477
  requestQueue.rejectRequest(method.responseID, hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallMethodError, error.message));
66234
66478
  Log.debug('Call API - Run Error: ', error);
66235
66479
  completeMethodRequestContext(method, error);
66480
+ return messageResponse;
66236
66481
  }
66237
66482
  finally {
66238
66483
  preWarmCallbackTask === null || preWarmCallbackTask === void 0 ? void 0 : preWarmCallbackTask.resolve();
@@ -66437,7 +66682,7 @@ function connectDeviceForBle(method, device, abortSignal, retryCount = 0) {
66437
66682
  var _a;
66438
66683
  return __awaiter(this, void 0, void 0, function* () {
66439
66684
  try {
66440
- if (device.wasInterruptedByUser()) {
66685
+ if ((abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.aborted) || device.wasInterruptedByUser()) {
66441
66686
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceInterruptedFromUser);
66442
66687
  }
66443
66688
  if (method.payload.forceProtocolDetection && device.hasDeviceAcquire()) {
@@ -66493,6 +66738,9 @@ function connectDeviceForBle(method, device, abortSignal, retryCount = 0) {
66493
66738
  }
66494
66739
  }
66495
66740
  catch (err) {
66741
+ if ((abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.aborted) || device.wasInterruptedByUser()) {
66742
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceInterruptedFromUser);
66743
+ }
66496
66744
  const requiresColdReconnect = isMissingDetectedProtocolV2Error(method, err);
66497
66745
  if ((hdShared.ERROR_CODES_REQUIRE_DISCONNECT.includes(err.errorCode) || requiresColdReconnect) &&
66498
66746
  device.mainId &&
@@ -66525,6 +66773,7 @@ const ensureConnected = (_context, method, connectId, pollingId, abortSignal) =>
66525
66773
  const POLL_INTERVAL_TIME = (method.payload && method.payload.pollIntervalTime) || 1000;
66526
66774
  const TIME_OUT = (method.payload && method.payload.timeout) || 10000;
66527
66775
  let timer = null;
66776
+ let lastInitializeError;
66528
66777
  Log.debug(`EnsureConnected function start, MAX_RETRY_COUNT=${MAX_RETRY_COUNT}, POLL_INTERVAL_TIME=${POLL_INTERVAL_TIME} `);
66529
66778
  const poll = (time = POLL_INTERVAL_TIME) => __awaiter(void 0, void 0, void 0, function* () {
66530
66779
  return new Promise((resolve, reject) => __awaiter(void 0, void 0, void 0, function* () {
@@ -66557,8 +66806,10 @@ const ensureConnected = (_context, method, connectId, pollingId, abortSignal) =>
66557
66806
  Log.debug('EnsureConnected function try count: ', tryCount, ' poll interval time: ', time);
66558
66807
  try {
66559
66808
  yield initDeviceList(method);
66809
+ lastInitializeError = undefined;
66560
66810
  }
66561
66811
  catch (error) {
66812
+ lastInitializeError = error;
66562
66813
  Log.debug('device list error: ', error);
66563
66814
  if ([
66564
66815
  hdShared.HardwareErrorCode.BridgeNotInstalled,
@@ -66571,6 +66822,7 @@ const ensureConnected = (_context, method, connectId, pollingId, abortSignal) =>
66571
66822
  }
66572
66823
  if (error.errorCode === hdShared.HardwareErrorCode.TransportNotConfigured) {
66573
66824
  yield TransportManager.configure();
66825
+ lastInitializeError = undefined;
66574
66826
  }
66575
66827
  }
66576
66828
  if (abort()) {
@@ -66629,6 +66881,7 @@ const ensureConnected = (_context, method, connectId, pollingId, abortSignal) =>
66629
66881
  hdShared.HardwareErrorCode.BleDeviceBondedCanceled,
66630
66882
  hdShared.HardwareErrorCode.BleCharacteristicNotifyError,
66631
66883
  hdShared.HardwareErrorCode.BleTimeoutError,
66884
+ hdShared.HardwareErrorCode.PollingTimeout,
66632
66885
  hdShared.HardwareErrorCode.BleWriteCharacteristicError,
66633
66886
  hdShared.HardwareErrorCode.BleAlreadyConnected,
66634
66887
  hdShared.HardwareErrorCode.FirmwareUpdateLimitOneDevice,
@@ -66639,6 +66892,8 @@ const ensureConnected = (_context, method, connectId, pollingId, abortSignal) =>
66639
66892
  hdShared.HardwareErrorCode.DeviceInterruptedFromUser,
66640
66893
  hdShared.HardwareErrorCode.CallQueueActionCancelled,
66641
66894
  ].includes(error.errorCode) ||
66895
+ (env === 'react-native' &&
66896
+ [hdShared.HardwareErrorCode.BleDeviceDisconnected, hdShared.HardwareErrorCode.PollingTimeout].includes(error.errorCode)) ||
66642
66897
  isTerminalBleStaleBondError(error) ||
66643
66898
  isDeviceIdentityMismatchError(error)) {
66644
66899
  reject(error);
@@ -66650,13 +66905,16 @@ const ensureConnected = (_context, method, connectId, pollingId, abortSignal) =>
66650
66905
  clearTimeout(timer);
66651
66906
  }
66652
66907
  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)) {
66908
+ const preserveWebUsbInitError = DataManager.isBrowserWebUsb(env) || DataManager.isDesktopWebUsb(env);
66909
+ const needsPermissionPrompt = DataManager.isBrowserWebUsb(env) && !((_u = method.payload) === null || _u === void 0 ? void 0 : _u.skipWebDevicePrompt);
66910
+ const fallbackError = needsPermissionPrompt
66911
+ ? hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.WebDeviceNotFoundOrNeedsPermission)
66912
+ : hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceNotFound);
66913
+ const errorToReject = preserveWebUsbInitError && lastInitializeError ? lastInitializeError : fallbackError;
66914
+ if (needsPermissionPrompt && errorToReject === fallbackError) {
66654
66915
  postMessage(createUiMessage(UI_REQUEST.WEB_DEVICE_PROMPT_ACCESS_PERMISSION));
66655
- reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.WebDeviceNotFoundOrNeedsPermission));
66656
- }
66657
- else {
66658
- reject(hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceNotFound));
66659
66916
  }
66917
+ reject(errorToReject);
66660
66918
  return;
66661
66919
  }
66662
66920
  if (abort()) {
@@ -66935,7 +67193,14 @@ class Core extends events.exports {
66935
67193
  this.prePendingCallPromises.delete(connectId);
66936
67194
  return;
66937
67195
  }
66938
- this.prePendingCallPromises.set(connectId, promise);
67196
+ const previous = this.prePendingCallPromises.get(connectId);
67197
+ const cleanupPromise = previous && previous !== promise
67198
+ ? Promise.all([previous, promise]).then(() => undefined)
67199
+ : promise;
67200
+ this.prePendingCallPromises.set(connectId, cleanupPromise);
67201
+ cleanupPromise.catch(error => {
67202
+ Log.warn('Device cancellation cleanup failed', { errorCode: error === null || error === void 0 ? void 0 : error.errorCode });
67203
+ });
66939
67204
  },
66940
67205
  removePrePendingCallPromise: (connectId, promise) => {
66941
67206
  if (this.prePendingCallPromises.get(connectId) === promise) {