@onekeyfe/hd-core 1.2.3-alpha.3 → 1.2.3-alpha.5

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 (65) hide show
  1. package/README.md +1 -1
  2. package/__tests__/AllNetworkGetAddressBase.tracing.test.ts +503 -10
  3. package/__tests__/DeviceCommands.test.ts +21 -0
  4. package/__tests__/core-error-output.test.ts +169 -1
  5. package/__tests__/device-lifecycle-events.test.ts +350 -2
  6. package/__tests__/open-wallet-session-error-response.test.ts +2 -2
  7. package/__tests__/open-wallet-session.test.ts +8 -411
  8. package/__tests__/protocol-v2-bootloader-mode.test.ts +8 -2
  9. package/__tests__/protocol-v2.test.ts +99 -0
  10. package/__tests__/public-device-state-api.test.ts +2 -7
  11. package/__tests__/search-devices.test.ts +196 -8
  12. package/__tests__/sol-sign-offchain-message.test.ts +0 -8
  13. package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
  14. package/dist/api/GetFeatures.d.ts.map +1 -1
  15. package/dist/api/GetPassphraseState.d.ts.map +1 -1
  16. package/dist/api/OpenWalletSession.d.ts.map +1 -1
  17. package/dist/api/SearchDevices.d.ts +2 -15
  18. package/dist/api/SearchDevices.d.ts.map +1 -1
  19. package/dist/api/allnetwork/AllNetworkGetAddress.d.ts +2 -0
  20. package/dist/api/allnetwork/AllNetworkGetAddress.d.ts.map +1 -1
  21. package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts +7 -1
  22. package/dist/api/allnetwork/AllNetworkGetAddressBase.d.ts.map +1 -1
  23. package/dist/api/allnetwork/AllNetworkGetAddressByLoop.d.ts.map +1 -1
  24. package/dist/api/device/DeviceVerify.d.ts.map +1 -1
  25. package/dist/core/RequestQueue.d.ts +1 -0
  26. package/dist/core/RequestQueue.d.ts.map +1 -1
  27. package/dist/core/index.d.ts +1 -0
  28. package/dist/core/index.d.ts.map +1 -1
  29. package/dist/data-manager/TransportManager.d.ts +2 -0
  30. package/dist/data-manager/TransportManager.d.ts.map +1 -1
  31. package/dist/device/Device.d.ts +2 -0
  32. package/dist/device/Device.d.ts.map +1 -1
  33. package/dist/device/DeviceCommands.d.ts +4 -4
  34. package/dist/device/DeviceCommands.d.ts.map +1 -1
  35. package/dist/index.d.ts +19 -21
  36. package/dist/index.js +456 -186
  37. package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
  38. package/dist/types/api/getFeatures.d.ts.map +1 -1
  39. package/dist/types/api/getPassphraseState.d.ts.map +1 -1
  40. package/dist/types/api/openWalletSession.d.ts +1 -10
  41. package/dist/types/api/openWalletSession.d.ts.map +1 -1
  42. package/dist/types/params.d.ts.map +1 -1
  43. package/dist/utils/patch.d.ts +1 -1
  44. package/dist/utils/patch.d.ts.map +1 -1
  45. package/package.json +4 -4
  46. package/src/api/FirmwareUpdateV4.ts +4 -0
  47. package/src/api/GetFeatures.ts +1 -0
  48. package/src/api/GetPassphraseState.ts +1 -0
  49. package/src/api/OpenWalletSession.ts +7 -77
  50. package/src/api/SearchDevices.ts +121 -27
  51. package/src/api/allnetwork/AllNetworkGetAddress.ts +79 -45
  52. package/src/api/allnetwork/AllNetworkGetAddressBase.ts +95 -24
  53. package/src/api/allnetwork/AllNetworkGetAddressByLoop.ts +3 -0
  54. package/src/api/device/DeviceVerify.ts +8 -0
  55. package/src/core/RequestQueue.ts +20 -0
  56. package/src/core/index.ts +135 -43
  57. package/src/data/messages/messages-protocol-v2.json +21 -0
  58. package/src/data-manager/TransportManager.ts +14 -3
  59. package/src/device/Device.ts +59 -28
  60. package/src/device/DeviceCommands.ts +6 -1
  61. package/src/protocols/protocol-v2/walletSession.ts +7 -0
  62. package/src/types/api/getFeatures.ts +2 -1
  63. package/src/types/api/getPassphraseState.ts +2 -5
  64. package/src/types/api/openWalletSession.ts +7 -19
  65. package/src/types/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
 
@@ -44170,6 +44209,8 @@ class DeviceCommands {
44170
44209
  const isProtocolV2DeviceBusyFailure = this.device.isProtocolV2() &&
44171
44210
  DEVICE_CONTROL_CALLS.has(callType) &&
44172
44211
  subcode === hdTransport.DeviceErrorCode.DeviceError_Busy;
44212
+ const isProtocolV2FirmwareUpdateBusyFailure = this.device.isProtocolV2() &&
44213
+ /^requested command not allowed while a firmware update is in progress$/i.test(normalizedMessage);
44173
44214
  const isLegacyProtocolV2LockedFailure = this.device.isProtocolV2() && /^device (?:is )?locked$/i.test(normalizedMessage);
44174
44215
  if (DEVICE_SESSION_CALLS.has(callType) &&
44175
44216
  subcode === hdTransport.DeviceSessionErrorCode.DeviceSessionError_InvalidSession) {
@@ -44220,7 +44261,7 @@ class DeviceCommands {
44220
44261
  firmwareMessage: message,
44221
44262
  });
44222
44263
  }
44223
- else if (isProtocolV2DeviceBusyFailure) {
44264
+ else if (isProtocolV2DeviceBusyFailure || isProtocolV2FirmwareUpdateBusyFailure) {
44224
44265
  error = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceBusy, message, {
44225
44266
  failureCode: code,
44226
44267
  subcode,
@@ -46324,6 +46365,10 @@ class Device extends events.exports {
46324
46365
  }
46325
46366
  this.invalidateProtocolV2RuntimeState();
46326
46367
  }
46368
+ waitForRunCleanup() {
46369
+ var _a;
46370
+ return (_a = this.runCleanupPromise) !== null && _a !== void 0 ? _a : Promise.resolve();
46371
+ }
46327
46372
  run(fn, options) {
46328
46373
  return __awaiter(this, void 0, void 0, function* () {
46329
46374
  if (this.runPromise) {
@@ -46441,44 +46486,68 @@ class Device extends events.exports {
46441
46486
  });
46442
46487
  }
46443
46488
  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
- }));
46489
+ var _a;
46490
+ const attempt = this.connectionAttempt;
46491
+ if (((_a = this.userInterruption) === null || _a === void 0 ? void 0 : _a.attempt) === attempt) {
46492
+ return this.userInterruption.promise;
46493
+ }
46494
+ const error = hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceInterruptedFromUser);
46495
+ this.interruptedAttempt = attempt;
46496
+ const cleanupPromise = this.runCleanupPromise;
46497
+ const { cancelableAction, commands, runPromise, deviceConnector, mainId } = this;
46498
+ const sendFallbackCancel = this.shouldSendFallbackProtocolCancel();
46499
+ const acquired = this.hasDeviceAcquire();
46500
+ const promise = (() => __awaiter(this, void 0, void 0, function* () {
46501
+ var _b;
46502
+ try {
46503
+ if (cancelableAction) {
46504
+ yield cancelableAction(error);
46505
+ }
46506
+ else if (sendFallbackCancel) {
46507
+ yield ((_b = commands === null || commands === void 0 ? void 0 : commands.cancelDevice) === null || _b === void 0 ? void 0 : _b.call(commands).catch(cancelError => {
46508
+ Log$h.debug('Protocol V2 fallback cancel error', cancelError);
46509
+ }));
46510
+ }
46511
+ else if (!acquired) {
46512
+ if (mainId && (deviceConnector === null || deviceConnector === void 0 ? void 0 : deviceConnector.disconnect)) {
46513
+ Log$h.debug('interruptionFromUser: disconnecting device without acquire, mainId:', mainId);
46514
+ yield deviceConnector.disconnect(mainId);
46515
+ }
46516
+ if (this.connectionAttempt === attempt)
46517
+ this.markTransportDisconnected();
46518
+ }
46519
+ yield (commands === null || commands === void 0 ? void 0 : commands.cancel());
46457
46520
  }
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);
46521
+ catch (cleanupError) {
46522
+ Log$h.warn('User cancellation cleanup failed; disconnecting device', cleanupError);
46523
+ if (mainId && (deviceConnector === null || deviceConnector === void 0 ? void 0 : deviceConnector.disconnect)) {
46524
+ yield deviceConnector.disconnect(mainId).catch(disconnectError => {
46525
+ Log$h.debug('User cancellation fallback disconnect failed', disconnectError);
46462
46526
  });
46463
46527
  }
46464
- this.markTransportDisconnected();
46528
+ if (this.connectionAttempt === attempt)
46529
+ this.markTransportDisconnected();
46465
46530
  }
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;
46531
+ finally {
46532
+ runPromise === null || runPromise === void 0 ? void 0 : runPromise.reject(error);
46533
+ if (this.runPromise === runPromise)
46534
+ this.runPromise = null;
46535
+ yield (cleanupPromise === null || cleanupPromise === void 0 ? void 0 : cleanupPromise.catch(() => undefined));
46470
46536
  }
46471
- yield (cleanupPromise === null || cleanupPromise === void 0 ? void 0 : cleanupPromise.catch(() => undefined));
46472
- });
46537
+ }))();
46538
+ this.userInterruption = { attempt, promise };
46539
+ return promise;
46473
46540
  }
46474
46541
  setCancelableAction(callback) {
46475
- this.cancelableAction = (e) => callback(e)
46542
+ const action = (e) => callback(e)
46476
46543
  .catch(e2 => {
46477
46544
  Log$h.debug('cancelableAction error', e2);
46478
46545
  })
46479
46546
  .finally(() => {
46480
- this.clearCancelableAction();
46547
+ if (this.cancelableAction === action)
46548
+ this.clearCancelableAction();
46481
46549
  });
46550
+ this.cancelableAction = action;
46482
46551
  }
46483
46552
  clearCancelableAction() {
46484
46553
  this.cancelableAction = undefined;
@@ -46588,7 +46657,7 @@ class Device extends events.exports {
46588
46657
  }
46589
46658
  hasUnexpectedMode(allow, require) {
46590
46659
  if (!this.isUnacquired()) {
46591
- if (this.isBootloader() && !this.isProtocolV2() && !allow.includes(UI_REQUEST.BOOTLOADER)) {
46660
+ if (this.isBootloader() && !allow.includes(UI_REQUEST.BOOTLOADER)) {
46592
46661
  return UI_REQUEST.BOOTLOADER;
46593
46662
  }
46594
46663
  if (!this.isInitialized() && !allow.includes(UI_REQUEST.NOT_INITIALIZE)) {
@@ -47210,6 +47279,48 @@ class PreInitialize extends BaseMethod {
47210
47279
  }
47211
47280
 
47212
47281
  const Log$e = getLogger(exports.LoggerNames.DevicePool);
47282
+ const getDescriptorKeys = (descriptor) => [descriptor.path, descriptor.id].filter((key) => typeof key === 'string' && key.length > 0);
47283
+ const isOwnedByActiveWebUsbRequest = (descriptor, requestQueue) => {
47284
+ if (!requestQueue)
47285
+ return false;
47286
+ return getDescriptorKeys(descriptor).some(key => requestQueue.getRequestTasksIdByConnectId(key).length > 0);
47287
+ };
47288
+ const getUsbHandle = (descriptor) => descriptor === null || descriptor === void 0 ? void 0 : descriptor.device;
47289
+ const getOwningRequestDevice = (descriptor, requestQueue) => {
47290
+ var _a, _b;
47291
+ if (!requestQueue)
47292
+ return undefined;
47293
+ const usbHandle = getUsbHandle(descriptor);
47294
+ if (usbHandle === undefined)
47295
+ return undefined;
47296
+ for (const key of getDescriptorKeys(descriptor)) {
47297
+ for (const requestId of requestQueue.getRequestTasksIdByConnectId(key)) {
47298
+ const device = (_a = requestQueue.getTask(requestId)) === null || _a === void 0 ? void 0 : _a.method.device;
47299
+ if ((device === null || device === void 0 ? void 0 : device.features) &&
47300
+ (device.mainId === key || ((_b = device.originalDescriptor) === null || _b === void 0 ? void 0 : _b.path) === key) &&
47301
+ getUsbHandle(device.originalDescriptor) === usbHandle) {
47302
+ return device;
47303
+ }
47304
+ }
47305
+ }
47306
+ return undefined;
47307
+ };
47308
+ const toSearchDeviceFromDescriptor = (descriptor) => {
47309
+ const connectId = descriptor.path || descriptor.id || null;
47310
+ return {
47311
+ connectId,
47312
+ uuid: '',
47313
+ serialNo: null,
47314
+ deviceId: null,
47315
+ deviceType: hdShared.EDeviceType.Unknown,
47316
+ name: descriptor.name || connectId || '',
47317
+ commType: descriptor.commType,
47318
+ };
47319
+ };
47320
+ const toSearchDevice = (device) => {
47321
+ const message = device.toMessageObject();
47322
+ return message ? message : null;
47323
+ };
47213
47324
  class SearchDevices extends BaseMethod {
47214
47325
  init() {
47215
47326
  this.useDevice = false;
@@ -47217,20 +47328,32 @@ class SearchDevices extends BaseMethod {
47217
47328
  this.skipForceUpdateCheck = true;
47218
47329
  }
47219
47330
  run() {
47220
- var _a, _b, _c, _d, _e;
47331
+ var _a, _b, _c, _d, _e, _f, _g;
47221
47332
  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
47333
  const env = DataManager.getSettings('env');
47334
+ const isWebUsb = env === 'webusb' || env === 'desktop-webusb';
47335
+ const requestQueue = (_a = this.context) === null || _a === void 0 ? void 0 : _a.requestQueue;
47336
+ const hasActiveWebUsbRequest = isWebUsb && ((_b = requestQueue === null || requestQueue === void 0 ? void 0 : requestQueue.getRequestTasksId().length) !== null && _b !== void 0 ? _b : 0) > 0;
47337
+ if (isWebUsb) {
47338
+ try {
47339
+ yield TransportManager.ensureInitialized();
47340
+ }
47341
+ catch (error) {
47342
+ Log$e.debug('WebUSB bring-up unavailable', error);
47343
+ }
47344
+ }
47345
+ if (!hasActiveWebUsbRequest)
47346
+ yield TransportManager.configure();
47347
+ const deviceDiff = yield ((_c = this.connector) === null || _c === void 0 ? void 0 : _c.enumerate());
47348
+ const devicesDescriptor = (_d = deviceDiff === null || deviceDiff === void 0 ? void 0 : deviceDiff.descriptors) !== null && _d !== void 0 ? _d : [];
47226
47349
  if (DataManager.isBleConnect(env)) {
47227
47350
  const devices = [];
47228
47351
  const seenIds = new Set();
47229
47352
  for (const device of devicesDescriptor) {
47230
- const lowerId = (_c = device.id) === null || _c === void 0 ? void 0 : _c.toLowerCase();
47353
+ const lowerId = (_e = device.id) === null || _e === void 0 ? void 0 : _e.toLowerCase();
47231
47354
  if (!seenIds.has(lowerId)) {
47232
47355
  seenIds.add(lowerId);
47233
- const rawBleName = (_e = (_d = device.name) !== null && _d !== void 0 ? _d : device.localName) !== null && _e !== void 0 ? _e : '';
47356
+ const rawBleName = (_g = (_f = device.name) !== null && _f !== void 0 ? _f : device.localName) !== null && _g !== void 0 ? _g : '';
47234
47357
  const bleName = hdShared.canonicalizePro2BleAdvertisementName(rawBleName);
47235
47358
  devices.push(Object.assign(Object.assign({}, device), { connectId: device.id, serialNo: null, uuid: '', deviceId: null, name: bleName || device.name, deviceType: getDeviceTypeByBleName(bleName) }));
47236
47359
  }
@@ -47239,22 +47362,34 @@ class SearchDevices extends BaseMethod {
47239
47362
  }
47240
47363
  const deviceList = [];
47241
47364
  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);
47365
+ if (hasActiveWebUsbRequest && isOwnedByActiveWebUsbRequest(descriptor, requestQueue)) {
47366
+ const cached = DevicePool.getDeviceByPath(descriptor.path);
47367
+ const known = (cached === null || cached === void 0 ? void 0 : cached.features) ? cached : getOwningRequestDevice(descriptor, requestQueue);
47368
+ const message = known ? toSearchDevice(known) : null;
47369
+ deviceList.push(message !== null && message !== void 0 ? message : toSearchDeviceFromDescriptor(descriptor));
47249
47370
  }
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 } : {})));
47371
+ else {
47372
+ try {
47373
+ const result = yield DevicePool.getDevices([descriptor], descriptor.path, {
47374
+ connectProtocol: undefined,
47375
+ forceProtocolDetection: true,
47376
+ refreshRuntimeState: true,
47377
+ });
47378
+ for (const device of result.deviceList) {
47379
+ const message = toSearchDevice(device);
47380
+ if (message)
47381
+ deviceList.push(message);
47382
+ }
47383
+ }
47384
+ catch (error) {
47385
+ const errorCode = error && typeof error === 'object' && 'errorCode' in error
47386
+ ? error.errorCode
47387
+ : undefined;
47388
+ Log$e.debug('Skip unavailable device during search', Object.assign({ path: descriptor.path }, (errorCode !== undefined ? { errorCode } : {})));
47389
+ }
47255
47390
  }
47256
47391
  }
47257
- return deviceList.map(device => device.toMessageObject());
47392
+ return deviceList;
47258
47393
  });
47259
47394
  }
47260
47395
  }
@@ -47588,15 +47723,6 @@ function validateResult(result, nonNullableFields, options) {
47588
47723
  }
47589
47724
  }
47590
47725
 
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
47726
  const wasResumed = (session) => !!session &&
47601
47727
  typeof session === 'object' &&
47602
47728
  'resumed' in session &&
@@ -47618,25 +47744,16 @@ const normalizeParams = (payload) => {
47618
47744
  throw invalidParameter('Parameter [mode] is required.');
47619
47745
  }
47620
47746
  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.');
47747
+ payload.mode !== OpenWalletSessionMode.SelectHidden) {
47748
+ throw invalidParameter('Parameter [mode] must be one of standard or select-hidden.');
47624
47749
  }
47625
47750
  if (payload.useEmptyPassphrase !== undefined || payload.initSession !== undefined) {
47626
47751
  throw invalidParameter('Legacy parameters [useEmptyPassphrase] and [initSession] are not supported by openWalletSession.');
47627
47752
  }
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 };
47753
+ if (payload.deviceId !== undefined || payload.passphraseState !== undefined) {
47754
+ throw invalidParameter('Parameters [deviceId] and [passphraseState] are not supported by openWalletSession. Pass passphraseState on later address and signing calls.');
47634
47755
  }
47635
- return {
47636
- mode: OpenWalletSessionMode.ResumeHidden,
47637
- deviceId: requiredString(payload.deviceId, 'deviceId'),
47638
- passphraseState: requiredString(payload.passphraseState, 'passphraseState'),
47639
- };
47756
+ return { mode: payload.mode };
47640
47757
  };
47641
47758
  class OpenWalletSession extends BaseMethod {
47642
47759
  getSupportedProtocols() {
@@ -47739,43 +47856,6 @@ class OpenWalletSession extends BaseMethod {
47739
47856
  resumed: wasResumed(session),
47740
47857
  };
47741
47858
  }
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
47859
  this.device.passphraseState = undefined;
47780
47860
  const walletStatus = yield ensureProtocolV2WalletStatus();
47781
47861
  if (isProtocolV2 && walletStatus.status.passphraseProtection !== true) {
@@ -49186,6 +49266,14 @@ class DeviceVerify extends BaseMethod {
49186
49266
  this.unlockPolicy = 'unlock-before-run';
49187
49267
  this.protocolV2PreUnlockPinType = hdTransport.DeviceSessionPinType.Any;
49188
49268
  this.useDevicePassphraseState = false;
49269
+ this.protocolV2UiInteraction = {
49270
+ request: 'button',
49271
+ source: 'method-lifecycle',
49272
+ reason: 'device-management',
49273
+ completion: 'operation-completed',
49274
+ deviceOnly: true,
49275
+ operation: 'deviceVerify',
49276
+ };
49189
49277
  validateParams(this.payload, [{ name: 'dataHex', type: 'hexString' }]);
49190
49278
  this.params = {
49191
49279
  data: formatAnyHex(this.payload.dataHex),
@@ -52325,6 +52413,7 @@ const PROTOCOL_V2_BOOTLOADER_RECONNECT_TIMEOUT = 90 * 1000;
52325
52413
  const PROTOCOL_V2_FINAL_RECONNECT_TIMEOUT = 3 * 60 * 1000;
52326
52414
  const PROTOCOL_V2_SHORT_RESPONSE_TIMEOUT = 5 * 1000;
52327
52415
  const PROTOCOL_V2_FIRMWARE_STATUS_RESPONSE_TIMEOUT = 15 * 1000;
52416
+ const PROTOCOL_V2_FILE_WRITE_RESPONSE_TIMEOUT = 30 * 1000;
52328
52417
  const PROTOCOL_V2_INSTALL_TIMEOUT = 5 * 60 * 1000;
52329
52418
  const PROTOCOL_V2_INSTALL_STATUS_INITIAL_DELAY = 1000;
52330
52419
  const PROTOCOL_V2_INSTALL_FINISHED_AFTER_DISCONNECT_POLLS = 4;
@@ -54540,6 +54629,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
54540
54629
  var _a;
54541
54630
  return __awaiter(this, void 0, void 0, function* () {
54542
54631
  const typedCall = this.device.getCommands().typedCall.bind(this.device.getCommands());
54632
+ const env = DataManager.getSettings('env');
54543
54633
  const writeRes = yield typedCall('FilesystemFileWrite', 'FilesystemFile', {
54544
54634
  file: {
54545
54635
  path: filePath,
@@ -54551,6 +54641,7 @@ class FirmwareUpdateV4 extends FirmwareUpdateBaseMethod {
54551
54641
  append: false,
54552
54642
  ui_percentage: progress !== null && progress !== void 0 ? progress : undefined,
54553
54643
  }, {
54644
+ timeoutMs: env === 'react-native' ? PROTOCOL_V2_FILE_WRITE_RESPONSE_TIMEOUT : undefined,
54554
54645
  writeWithResponse: false,
54555
54646
  onWriteCompleted: () => undefined,
54556
54647
  });
@@ -55908,6 +55999,8 @@ class AllNetworkGetAddressBase extends BaseMethod {
55908
55999
  constructor() {
55909
56000
  super(...arguments);
55910
56001
  this.abortController = null;
56002
+ this.loadingCleanupInBackground = false;
56003
+ this.protocolV2ResumedSeedDomains = new Set();
55911
56004
  }
55912
56005
  getSupportedProtocols() {
55913
56006
  return ['V1', 'V2'];
@@ -55943,7 +56036,20 @@ class AllNetworkGetAddressBase extends BaseMethod {
55943
56036
  _originalIndex: originalIndex,
55944
56037
  };
55945
56038
  }
55946
- callMethod(methodName, params, rootFingerprint) {
56039
+ hasProtocolV2WalletResume(deriveCardano) {
56040
+ if (deriveCardano) {
56041
+ return this.protocolV2ResumedSeedDomains.has('cardano');
56042
+ }
56043
+ return (this.protocolV2ResumedSeedDomains.has('standard') ||
56044
+ this.protocolV2ResumedSeedDomains.has('cardano'));
56045
+ }
56046
+ markProtocolV2WalletResumed(deriveCardano) {
56047
+ this.protocolV2ResumedSeedDomains.add('standard');
56048
+ if (deriveCardano) {
56049
+ this.protocolV2ResumedSeedDomains.add('cardano');
56050
+ }
56051
+ }
56052
+ callMethod(methodName, params, rootFingerprint, postMessage = this.postMessage) {
55947
56053
  var _a, _b, _c;
55948
56054
  return __awaiter(this, void 0, void 0, function* () {
55949
56055
  const method = findMethod({
@@ -55952,7 +56058,7 @@ class AllNetworkGetAddressBase extends BaseMethod {
55952
56058
  payload: Object.assign({ connectId: this.payload.connectId, deviceId: this.payload.deviceId, method: methodName }, params),
55953
56059
  });
55954
56060
  method.connector = this.connector;
55955
- method.postMessage = this.postMessage;
56061
+ method.postMessage = postMessage;
55956
56062
  if (this.context) {
55957
56063
  (_a = method.setContext) === null || _a === void 0 ? void 0 : _a.call(method, this.context);
55958
56064
  }
@@ -56005,11 +56111,14 @@ class AllNetworkGetAddressBase extends BaseMethod {
56005
56111
  const useEmptyPassphrase = this.payload.useEmptyPassphrase === true;
56006
56112
  const deriveCardano = method.name.startsWith('cardano') ? true : undefined;
56007
56113
  const shouldResumeWalletSession = useEmptyPassphrase || !!this.payload.passphraseState;
56008
- if (this.device.isProtocolV2() && shouldResumeWalletSession) {
56114
+ if (this.device.isProtocolV2() &&
56115
+ shouldResumeWalletSession &&
56116
+ !this.hasProtocolV2WalletResume(deriveCardano)) {
56009
56117
  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
56118
  if (!passphraseStateSafety) {
56011
56119
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceCheckPassphraseStateError);
56012
56120
  }
56121
+ this.markProtocolV2WalletResumed(deriveCardano);
56013
56122
  }
56014
56123
  }),
56015
56124
  });
@@ -56045,27 +56154,63 @@ class AllNetworkGetAddressBase extends BaseMethod {
56045
56154
  return result;
56046
56155
  });
56047
56156
  }
56048
- run() {
56157
+ stopAllNetworkLoading(canSend = true) {
56049
56158
  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));
56159
+ const commands = this.loadingCommands;
56160
+ this.loadingCommands = undefined;
56161
+ if (!canSend || !commands || commands.disposed || commands !== this.device.commands)
56162
+ return;
56163
+ try {
56164
+ yield commands.typedCall('DeviceAnimationControl', 'Success', {
56165
+ action: hdTransport.Messages.DeviceAnimationAction.AnimationAction_Stop,
56166
+ });
56058
56167
  }
56059
- if (res.message.root_fingerprint == null) {
56060
- throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallMethodInvalidParameter);
56168
+ catch (_a) {
56061
56169
  }
56062
- this.abortController = new AbortController();
56063
- return this.getAllNetworkAddress(res.message.root_fingerprint).catch(e => {
56170
+ });
56171
+ }
56172
+ run() {
56173
+ return __awaiter(this, void 0, void 0, function* () {
56174
+ this.loadingCleanupInBackground = false;
56175
+ try {
56176
+ if (this.device.isProtocolV2() &&
56177
+ (this.device.getCurrentDeviceType() === hdShared.EDeviceType.Pro2 ||
56178
+ this.device.getCurrentDeviceType() === hdShared.EDeviceType.Neo)) {
56179
+ const protocolInfo = yield this.device.ensureProtocolV2RuntimeContext();
56180
+ if (supportsProtocolV2Message(protocolInfo, 60461)) {
56181
+ const { commands } = this.device;
56182
+ yield commands.typedCall('DeviceAnimationControl', 'Success', {
56183
+ action: hdTransport.Messages.DeviceAnimationAction.AnimationAction_Start,
56184
+ });
56185
+ this.loadingCommands = commands;
56186
+ }
56187
+ }
56188
+ const res = yield this.device.commands.typedCall('GetPublicKey', 'PublicKey', {
56189
+ address_n: [toHardened(44), toHardened(1), toHardened(0)],
56190
+ coin_name: 'Testnet',
56191
+ script_type: 'SPENDADDRESS',
56192
+ show_display: false,
56193
+ });
56194
+ if (!this.device.isProtocolV2()) {
56195
+ this.postMessage(createUiMessage(UI_REQUEST.CLOSE_UI_PIN_WINDOW));
56196
+ }
56197
+ if (res.message.root_fingerprint == null) {
56198
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallMethodInvalidParameter);
56199
+ }
56200
+ this.abortController = new AbortController();
56201
+ return yield this.getAllNetworkAddress(res.message.root_fingerprint);
56202
+ }
56203
+ catch (e) {
56204
+ yield this.stopAllNetworkLoading(false);
56064
56205
  if (e instanceof hdShared.HardwareError && e.errorCode === hdShared.HardwareErrorCode.RepeatUnlocking) {
56065
56206
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RepeatUnlocking, e.message);
56066
56207
  }
56067
56208
  throw e;
56068
- });
56209
+ }
56210
+ finally {
56211
+ if (!this.loadingCleanupInBackground)
56212
+ yield this.stopAllNetworkLoading();
56213
+ }
56069
56214
  });
56070
56215
  }
56071
56216
  }
@@ -56126,57 +56271,83 @@ function handleSkippableHardwareError(e, device, method) {
56126
56271
  }
56127
56272
 
56128
56273
  class AllNetworkGetAddress extends AllNetworkGetAddressBase {
56274
+ checkAborted() {
56275
+ var _a;
56276
+ if ((_a = this.abortController) === null || _a === void 0 ? void 0 : _a.signal.aborted) {
56277
+ throw new Error(hdShared.HardwareErrorCodeMessage[hdShared.HardwareErrorCode.RepeatUnlocking]);
56278
+ }
56279
+ }
56280
+ callAddressGroup(methodName, params, rootFingerprint) {
56281
+ return __awaiter(this, void 0, void 0, function* () {
56282
+ const methodCallParams = { bundle: params.map(param => (Object.assign({}, param.params))) };
56283
+ if (!this.device.isProtocolV2() || params.length === 1) {
56284
+ return this.callMethod(methodName, methodCallParams, rootFingerprint);
56285
+ }
56286
+ const postedAddressCounts = new Map();
56287
+ let runningIndividually = false;
56288
+ const postMessage = message => {
56289
+ var _a;
56290
+ if (message.type === UI_REQUEST.PREVIOUS_ADDRESS_RESULT) {
56291
+ const { path, address } = message.payload.data;
56292
+ const key = JSON.stringify([path, address]);
56293
+ const count = (_a = postedAddressCounts.get(key)) !== null && _a !== void 0 ? _a : 0;
56294
+ if (runningIndividually && count > 0) {
56295
+ postedAddressCounts.set(key, count - 1);
56296
+ return;
56297
+ }
56298
+ if (!runningIndividually)
56299
+ postedAddressCounts.set(key, count + 1);
56300
+ }
56301
+ this.postMessage(message);
56302
+ };
56303
+ if (params.every(param => param._originRequestParams.showOnOneKey === false)) {
56304
+ const response = yield this.callMethod(methodName, methodCallParams, rootFingerprint, postMessage);
56305
+ if (response.some(item => item.success))
56306
+ return response;
56307
+ }
56308
+ runningIndividually = true;
56309
+ const responses = [];
56310
+ for (const param of params) {
56311
+ this.checkAborted();
56312
+ const response = yield this.callMethod(methodName, { bundle: [Object.assign({}, param.params)] }, rootFingerprint, postMessage);
56313
+ responses.push(...response);
56314
+ }
56315
+ return responses;
56316
+ });
56317
+ }
56129
56318
  getAllNetworkAddress(rootFingerprint) {
56130
- var _a, _b, _c, _d;
56131
56319
  return __awaiter(this, void 0, void 0, function* () {
56132
56320
  const responses = [];
56133
- const resultMap = {};
56134
56321
  const { bundle } = this.payload;
56135
56322
  const methodParams = bundle.map((param, index) => this.generateMethodName({
56136
56323
  network: param.network,
56137
56324
  payload: param,
56138
56325
  originalIndex: index,
56139
56326
  }));
56140
- const groupedMethodParams = methodParams.reduce((groups, param) => {
56327
+ const methodGroups = methodParams.reduce((groups, param) => {
56141
56328
  var _a;
56142
56329
  const group = (_a = groups.get(param.methodName)) !== null && _a !== void 0 ? _a : [];
56143
56330
  group.push(param);
56144
56331
  groups.set(param.methodName, group);
56145
56332
  return groups;
56146
56333
  }, 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]);
56334
+ let processed = 0;
56335
+ for (const [methodName, params] of methodGroups.entries()) {
56336
+ this.checkAborted();
56337
+ const response = yield this.callAddressGroup(methodName, params, rootFingerprint);
56338
+ this.checkAborted();
56339
+ for (let index = 0; index < params.length; index++) {
56340
+ const { _originRequestParams, _originalIndex } = params[index];
56341
+ responses[_originalIndex] = Object.assign(Object.assign({}, _originRequestParams), response[index]);
56168
56342
  }
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);
56343
+ processed += params.length;
56344
+ if (bundle.length > 1) {
56345
+ const progress = Math.round((processed / bundle.length) * 100);
56171
56346
  this.postMessage(createUiMessage(UI_REQUEST.DEVICE_PROGRESS, { progress }));
56172
56347
  }
56173
- i++;
56174
- }
56175
- for (let i = 0; i < bundle.length; i++) {
56176
- responses.push(resultMap[i]);
56177
56348
  }
56178
56349
  this.abortController = null;
56179
- return Promise.resolve(responses);
56350
+ return responses;
56180
56351
  });
56181
56352
  }
56182
56353
  }
@@ -56192,6 +56363,7 @@ class AllNetworkGetAddressByLoop extends AllNetworkGetAddressBase {
56192
56363
  throw new Error('callbackIdFinish is required');
56193
56364
  }
56194
56365
  const bundle = this.payload.bundle || [this.payload];
56366
+ this.loadingCleanupInBackground = true;
56195
56367
  const callbackPromise = this.processCallbacksInBackground(bundle, rootFingerprint, callbackId, callbackIdFinish);
56196
56368
  this.device.pendingCallbackPromise = hdShared.createDeferred(callbackPromise);
56197
56369
  if (this.context && this.payload.connectId) {
@@ -56232,6 +56404,7 @@ class AllNetworkGetAddressByLoop extends AllNetworkGetAddressBase {
56232
56404
  });
56233
56405
  }
56234
56406
  catch (error) {
56407
+ yield this.stopAllNetworkLoading(false);
56235
56408
  let errorCode = error.errorCode || error.code;
56236
56409
  let errorMessage = error.message;
56237
56410
  if (error instanceof hdShared.HardwareError) {
@@ -56259,6 +56432,7 @@ class AllNetworkGetAddressByLoop extends AllNetworkGetAddressBase {
56259
56432
  });
56260
56433
  }
56261
56434
  finally {
56435
+ yield this.stopAllNetworkLoading();
56262
56436
  (_c = this.context) === null || _c === void 0 ? void 0 : _c.cancelCallbackTasks(this.payload.connectId);
56263
56437
  this.abortController = null;
56264
56438
  }
@@ -65584,6 +65758,29 @@ class RequestQueue {
65584
65758
  getTask(requestId) {
65585
65759
  return this.requestQueue.get(requestId);
65586
65760
  }
65761
+ waitForTask(task, pending) {
65762
+ return __awaiter(this, void 0, void 0, function* () {
65763
+ const signal = task.method.abortSignal;
65764
+ const cancellationError = () => hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallQueueActionCancelled);
65765
+ if (signal === null || signal === void 0 ? void 0 : signal.aborted)
65766
+ throw cancellationError();
65767
+ let onAbort;
65768
+ try {
65769
+ const cancelled = new Promise((_, reject) => {
65770
+ onAbort = () => reject(cancellationError());
65771
+ signal === null || signal === void 0 ? void 0 : signal.addEventListener('abort', onAbort, { once: true });
65772
+ });
65773
+ const result = yield Promise.race([pending(), cancelled]);
65774
+ if (signal === null || signal === void 0 ? void 0 : signal.aborted)
65775
+ throw cancellationError();
65776
+ return result;
65777
+ }
65778
+ finally {
65779
+ if (onAbort)
65780
+ signal === null || signal === void 0 ? void 0 : signal.removeEventListener('abort', onAbort);
65781
+ }
65782
+ });
65783
+ }
65587
65784
  getAbortController(requestId) {
65588
65785
  var _a;
65589
65786
  return (_a = this.requestQueue.get(requestId)) === null || _a === void 0 ? void 0 : _a.abortController;
@@ -65783,7 +65980,8 @@ const createUiProgressMessageFilter = (intervalMs = DEFAULT_UI_PROGRESS_INTERVAL
65783
65980
 
65784
65981
  const Log = getLogger(exports.LoggerNames.Core);
65785
65982
  const PRE_INITIALIZE_TTL_MS = 60 * 1000;
65786
- const PRE_PENDING_CALL_TIMEOUT_MS = 15 * 1000;
65983
+ const PRE_PENDING_CALL_TIMEOUT_MS = 5 * 1000;
65984
+ const PRO2_USB_SIGNING_COOLDOWN_MS = 1000;
65787
65985
  const preWarmInflight = new Map();
65788
65986
  const preWarmDoneAt = new Map();
65789
65987
  function resolveDeriveCardano(method) {
@@ -65862,6 +66060,7 @@ const callAPI = (context, message) => __awaiter(void 0, void 0, void 0, function
65862
66060
  }
65863
66061
  };
65864
66062
  (_a = method.setContext) === null || _a === void 0 ? void 0 : _a.call(method, context);
66063
+ method.context = context;
65865
66064
  method.requestContext = createRequestContext(method.responseID, method.name, {
65866
66065
  sdkInstanceId: context.sdkInstanceId,
65867
66066
  connectId: method.connectId,
@@ -65879,7 +66078,11 @@ const callAPI = (context, message) => __awaiter(void 0, void 0, void 0, function
65879
66078
  if (!method.useDevice) {
65880
66079
  updateMethodRequestContext(method, { status: 'running' });
65881
66080
  try {
65882
- const response = yield method.run();
66081
+ const env = DataManager.getSettings('env');
66082
+ const response = method.name === 'searchDevices' &&
66083
+ (DataManager.isBrowserWebUsb(env) || DataManager.isDesktopWebUsb(env))
66084
+ ? yield context.methodSynchronize(() => method.run(), 'webusb-discovery')
66085
+ : yield method.run();
65883
66086
  completeMethodRequestContext(method);
65884
66087
  return createResponseMessage(method.responseID, true, response);
65885
66088
  }
@@ -65951,6 +66154,7 @@ const waitForPendingPromise = (connectId, getPrePendingCallPromise, removePrePen
65951
66154
  Log.debug('pre pending call promise before call method, wait for it');
65952
66155
  let timer;
65953
66156
  let timedOut = false;
66157
+ let completed = false;
65954
66158
  try {
65955
66159
  yield Promise.race([
65956
66160
  pendingPromise,
@@ -65961,13 +66165,13 @@ const waitForPendingPromise = (connectId, getPrePendingCallPromise, removePrePen
65961
66165
  }, PRE_PENDING_CALL_TIMEOUT_MS);
65962
66166
  }),
65963
66167
  ]);
65964
- }
65965
- catch (error) {
66168
+ completed = !timedOut;
65966
66169
  }
65967
66170
  finally {
65968
66171
  if (timer)
65969
66172
  clearTimeout(timer);
65970
- removePrePendingCallPromise === null || removePrePendingCallPromise === void 0 ? void 0 : removePrePendingCallPromise(connectId, pendingPromise);
66173
+ if (timedOut || completed)
66174
+ removePrePendingCallPromise === null || removePrePendingCallPromise === void 0 ? void 0 : removePrePendingCallPromise(connectId, pendingPromise);
65971
66175
  }
65972
66176
  if (timedOut) {
65973
66177
  Log.warn('pre pending call promise timed out before call method', { connectId });
@@ -65975,8 +66179,19 @@ const waitForPendingPromise = (connectId, getPrePendingCallPromise, removePrePen
65975
66179
  Log.debug('pre pending call promise before call method done');
65976
66180
  }
65977
66181
  });
66182
+ function getPostCallPendingPromise(method, device) {
66183
+ const cleanupPromise = device.waitForRunCleanup();
66184
+ const env = DataManager.getSettings('env');
66185
+ const deviceType = device.getCurrentDeviceType();
66186
+ const requiresSigningCooldown = method.name.includes('Sign') &&
66187
+ (deviceType === hdShared.EDeviceType.Pro2 || deviceType === hdShared.EDeviceType.Neo) &&
66188
+ (DataManager.isBrowserWebUsb(env) || DataManager.isDesktopWebUsb(env) || env === 'node-usb');
66189
+ return requiresSigningCooldown
66190
+ ? cleanupPromise.then(() => wait(PRO2_USB_SIGNING_COOLDOWN_MS)).then(() => undefined)
66191
+ : cleanupPromise;
66192
+ }
65978
66193
  const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, void 0, function* () {
65979
- var _d, _e, _f, _g, _h, _j, _k;
66194
+ var _d, _e, _f, _g, _h, _j;
65980
66195
  let messageResponse;
65981
66196
  const { requestQueue, getPrePendingCallPromise, removePrePendingCallPromise } = context;
65982
66197
  updateMethodRequestContext(method, { status: 'running' });
@@ -65990,21 +66205,42 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
65990
66205
  Log.debug('passphrase state change, clear device cache');
65991
66206
  DevicePool.clearDeviceCache(method.payload.connectId);
65992
66207
  }
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
66208
  const task = requestQueue.createTask(method);
65998
66209
  let preWarmCallbackTask;
65999
- if (method.isPreWarmSignal && method.connectId) {
66000
- preWarmCallbackTask = hdShared.createDeferred();
66001
- context.registerCallbackTask(method.connectId, preWarmCallbackTask);
66002
- }
66003
66210
  let device;
66004
66211
  try {
66005
- const connectId = (_e = method.connectId) !== null && _e !== void 0 ? _e : '';
66212
+ const connectId = (_d = method.connectId) !== null && _d !== void 0 ? _d : '';
66213
+ if (connectId) {
66214
+ yield requestQueue.waitForTask(task, () => context.waitForCallbackTasks(connectId));
66215
+ }
66216
+ yield requestQueue.waitForTask(task, () => {
66217
+ var _a;
66218
+ return waitForPendingPromise((_a = method.connectId) !== null && _a !== void 0 ? _a : '', getPrePendingCallPromise, removePrePendingCallPromise);
66219
+ });
66220
+ if (method.isPreWarmSignal && method.connectId) {
66221
+ preWarmCallbackTask = hdShared.createDeferred();
66222
+ context.registerCallbackTask(method.connectId, preWarmCallbackTask);
66223
+ }
66006
66224
  const pollingId = pollingManager.start(connectId);
66007
- device = yield ensureConnected(context, method, connectId, pollingId, (_f = task.abortController) === null || _f === void 0 ? void 0 : _f.signal);
66225
+ const env = DataManager.getSettings('env');
66226
+ const connect = () => ensureConnected(context, method, connectId, pollingId, method.abortSignal);
66227
+ if (DataManager.isBrowserWebUsb(env) || DataManager.isDesktopWebUsb(env)) {
66228
+ const connectPromise = context.methodSynchronize(() => __awaiter(void 0, void 0, void 0, function* () {
66229
+ var _k;
66230
+ if ((_k = method.abortSignal) === null || _k === void 0 ? void 0 : _k.aborted) {
66231
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallQueueActionCancelled);
66232
+ }
66233
+ return connect();
66234
+ }), 'webusb-discovery');
66235
+ connectPromise.catch(() => undefined);
66236
+ device = yield requestQueue.waitForTask(task, () => connectPromise);
66237
+ }
66238
+ else {
66239
+ device = yield connect();
66240
+ }
66241
+ if ((_e = method.abortSignal) === null || _e === void 0 ? void 0 : _e.aborted) {
66242
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallQueueActionCancelled);
66243
+ }
66008
66244
  }
66009
66245
  catch (e) {
66010
66246
  preWarmCallbackTask === null || preWarmCallbackTask === void 0 ? void 0 : preWarmCallbackTask.resolve();
@@ -66019,7 +66255,7 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
66019
66255
  requestQueue.releaseTask(method.responseID);
66020
66256
  return createResponseMessage(method.responseID, false, { error: e });
66021
66257
  }
66022
- if ((_g = method.payload) === null || _g === void 0 ? void 0 : _g.onlyConnectBleDevice) {
66258
+ if ((_f = method.payload) === null || _f === void 0 ? void 0 : _f.onlyConnectBleDevice) {
66023
66259
  preWarmCallbackTask === null || preWarmCallbackTask === void 0 ? void 0 : preWarmCallbackTask.resolve();
66024
66260
  Log.debug('Call API - only connect ble device: ', device === null || device === void 0 ? void 0 : device.mainId);
66025
66261
  completeMethodRequestContext(method);
@@ -66027,11 +66263,11 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
66027
66263
  return createResponseMessage(method.responseID, true, null);
66028
66264
  }
66029
66265
  Log.debug('Call API - setDevice: ', device.mainId);
66030
- (_h = method.setDevice) === null || _h === void 0 ? void 0 : _h.call(method, device);
66266
+ (_g = method.setDevice) === null || _g === void 0 ? void 0 : _g.call(method, device);
66031
66267
  method.context = context;
66032
66268
  updateMethodRequestContext(method, {
66033
66269
  deviceInstanceId: device.instanceId,
66034
- commandsInstanceId: (_j = device.commands) === null || _j === void 0 ? void 0 : _j.instanceId,
66270
+ commandsInstanceId: (_h = device.commands) === null || _h === void 0 ? void 0 : _h.instanceId,
66035
66271
  });
66036
66272
  const activeRequests = getActiveRequestsByDeviceInstance(device.instanceId);
66037
66273
  if (activeRequests.length > 0) {
@@ -66057,10 +66293,14 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
66057
66293
  device.beginProtocolV2UiInteraction();
66058
66294
  device.on(DEVICE.SELECT_DEVICE_FOR_SWITCH_FIRMWARE_WEB_DEVICE, onSelectDeviceForSwitchFirmwareWebDeviceHandler);
66059
66295
  try {
66060
- if (method.connectId) {
66061
- yield context.waitForCallbackTasks(method.connectId, preWarmCallbackTask);
66296
+ const { connectId } = method;
66297
+ if (connectId) {
66298
+ yield requestQueue.waitForTask(task, () => context.waitForCallbackTasks(connectId, preWarmCallbackTask));
66062
66299
  }
66063
- yield waitForPendingPromise((_k = method.connectId) !== null && _k !== void 0 ? _k : '', getPrePendingCallPromise, removePrePendingCallPromise);
66300
+ yield requestQueue.waitForTask(task, () => {
66301
+ var _a;
66302
+ return waitForPendingPromise((_a = method.connectId) !== null && _a !== void 0 ? _a : '', getPrePendingCallPromise, removePrePendingCallPromise);
66303
+ });
66064
66304
  const inner = () => __awaiter(void 0, void 0, void 0, function* () {
66065
66305
  var _l, _m;
66066
66306
  method.assertProtocolSupported(device.getProtocol(), device.getCurrentFirmwareType());
@@ -66187,6 +66427,9 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
66187
66427
  }),
66188
66428
  });
66189
66429
  messageResponse = createResponseMessage(method.responseID, true, response);
66430
+ if (method.connectId) {
66431
+ context.setPrePendingCallPromise(method.connectId, getPostCallPendingPromise(method, device));
66432
+ }
66190
66433
  requestQueue.resolveRequest(method.responseID, messageResponse);
66191
66434
  completeMethodRequestContext(method);
66192
66435
  }
@@ -66197,6 +66440,9 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
66197
66440
  }
66198
66441
  Log.debug(`Call API - Inner Method Run Error`, error);
66199
66442
  messageResponse = createResponseMessage(method.responseID, false, { error });
66443
+ if (method.connectId) {
66444
+ context.setPrePendingCallPromise(method.connectId, getPostCallPendingPromise(method, device));
66445
+ }
66200
66446
  requestQueue.resolveRequest(method.responseID, messageResponse);
66201
66447
  completeMethodRequestContext(method, error);
66202
66448
  if (error instanceof hdShared.HardwareError &&
@@ -66215,6 +66461,9 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
66215
66461
  });
66216
66462
  Log.debug('Call API - Device Run: ', device.mainId);
66217
66463
  const runOptions = Object.assign({ keepSession: method.payload.keepSession, skipInitialize: canSkipInitialize(method, device) }, parseInitOptions(method));
66464
+ if ((_j = method.abortSignal) === null || _j === void 0 ? void 0 : _j.aborted) {
66465
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallQueueActionCancelled);
66466
+ }
66218
66467
  const deviceRun = () => device.run(inner, runOptions);
66219
66468
  task.callPromise = hdShared.createDeferred(deviceRun);
66220
66469
  try {
@@ -66233,6 +66482,7 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
66233
66482
  requestQueue.rejectRequest(method.responseID, hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.CallMethodError, error.message));
66234
66483
  Log.debug('Call API - Run Error: ', error);
66235
66484
  completeMethodRequestContext(method, error);
66485
+ return messageResponse;
66236
66486
  }
66237
66487
  finally {
66238
66488
  preWarmCallbackTask === null || preWarmCallbackTask === void 0 ? void 0 : preWarmCallbackTask.resolve();
@@ -66437,7 +66687,7 @@ function connectDeviceForBle(method, device, abortSignal, retryCount = 0) {
66437
66687
  var _a;
66438
66688
  return __awaiter(this, void 0, void 0, function* () {
66439
66689
  try {
66440
- if (device.wasInterruptedByUser()) {
66690
+ if ((abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.aborted) || device.wasInterruptedByUser()) {
66441
66691
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceInterruptedFromUser);
66442
66692
  }
66443
66693
  if (method.payload.forceProtocolDetection && device.hasDeviceAcquire()) {
@@ -66493,6 +66743,9 @@ function connectDeviceForBle(method, device, abortSignal, retryCount = 0) {
66493
66743
  }
66494
66744
  }
66495
66745
  catch (err) {
66746
+ if ((abortSignal === null || abortSignal === void 0 ? void 0 : abortSignal.aborted) || device.wasInterruptedByUser()) {
66747
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceInterruptedFromUser);
66748
+ }
66496
66749
  const requiresColdReconnect = isMissingDetectedProtocolV2Error(method, err);
66497
66750
  if ((hdShared.ERROR_CODES_REQUIRE_DISCONNECT.includes(err.errorCode) || requiresColdReconnect) &&
66498
66751
  device.mainId &&
@@ -66525,6 +66778,7 @@ const ensureConnected = (_context, method, connectId, pollingId, abortSignal) =>
66525
66778
  const POLL_INTERVAL_TIME = (method.payload && method.payload.pollIntervalTime) || 1000;
66526
66779
  const TIME_OUT = (method.payload && method.payload.timeout) || 10000;
66527
66780
  let timer = null;
66781
+ let lastInitializeError;
66528
66782
  Log.debug(`EnsureConnected function start, MAX_RETRY_COUNT=${MAX_RETRY_COUNT}, POLL_INTERVAL_TIME=${POLL_INTERVAL_TIME} `);
66529
66783
  const poll = (time = POLL_INTERVAL_TIME) => __awaiter(void 0, void 0, void 0, function* () {
66530
66784
  return new Promise((resolve, reject) => __awaiter(void 0, void 0, void 0, function* () {
@@ -66557,8 +66811,10 @@ const ensureConnected = (_context, method, connectId, pollingId, abortSignal) =>
66557
66811
  Log.debug('EnsureConnected function try count: ', tryCount, ' poll interval time: ', time);
66558
66812
  try {
66559
66813
  yield initDeviceList(method);
66814
+ lastInitializeError = undefined;
66560
66815
  }
66561
66816
  catch (error) {
66817
+ lastInitializeError = error;
66562
66818
  Log.debug('device list error: ', error);
66563
66819
  if ([
66564
66820
  hdShared.HardwareErrorCode.BridgeNotInstalled,
@@ -66571,6 +66827,7 @@ const ensureConnected = (_context, method, connectId, pollingId, abortSignal) =>
66571
66827
  }
66572
66828
  if (error.errorCode === hdShared.HardwareErrorCode.TransportNotConfigured) {
66573
66829
  yield TransportManager.configure();
66830
+ lastInitializeError = undefined;
66574
66831
  }
66575
66832
  }
66576
66833
  if (abort()) {
@@ -66629,6 +66886,7 @@ const ensureConnected = (_context, method, connectId, pollingId, abortSignal) =>
66629
66886
  hdShared.HardwareErrorCode.BleDeviceBondedCanceled,
66630
66887
  hdShared.HardwareErrorCode.BleCharacteristicNotifyError,
66631
66888
  hdShared.HardwareErrorCode.BleTimeoutError,
66889
+ hdShared.HardwareErrorCode.PollingTimeout,
66632
66890
  hdShared.HardwareErrorCode.BleWriteCharacteristicError,
66633
66891
  hdShared.HardwareErrorCode.BleAlreadyConnected,
66634
66892
  hdShared.HardwareErrorCode.FirmwareUpdateLimitOneDevice,
@@ -66639,6 +66897,8 @@ const ensureConnected = (_context, method, connectId, pollingId, abortSignal) =>
66639
66897
  hdShared.HardwareErrorCode.DeviceInterruptedFromUser,
66640
66898
  hdShared.HardwareErrorCode.CallQueueActionCancelled,
66641
66899
  ].includes(error.errorCode) ||
66900
+ (env === 'react-native' &&
66901
+ [hdShared.HardwareErrorCode.BleDeviceDisconnected, hdShared.HardwareErrorCode.PollingTimeout].includes(error.errorCode)) ||
66642
66902
  isTerminalBleStaleBondError(error) ||
66643
66903
  isDeviceIdentityMismatchError(error)) {
66644
66904
  reject(error);
@@ -66650,13 +66910,16 @@ const ensureConnected = (_context, method, connectId, pollingId, abortSignal) =>
66650
66910
  clearTimeout(timer);
66651
66911
  }
66652
66912
  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)) {
66913
+ const preserveWebUsbInitError = DataManager.isBrowserWebUsb(env) || DataManager.isDesktopWebUsb(env);
66914
+ const needsPermissionPrompt = DataManager.isBrowserWebUsb(env) && !((_u = method.payload) === null || _u === void 0 ? void 0 : _u.skipWebDevicePrompt);
66915
+ const fallbackError = needsPermissionPrompt
66916
+ ? hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.WebDeviceNotFoundOrNeedsPermission)
66917
+ : hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceNotFound);
66918
+ const errorToReject = preserveWebUsbInitError && lastInitializeError ? lastInitializeError : fallbackError;
66919
+ if (needsPermissionPrompt && errorToReject === fallbackError) {
66654
66920
  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
66921
  }
66922
+ reject(errorToReject);
66660
66923
  return;
66661
66924
  }
66662
66925
  if (abort()) {
@@ -66935,7 +67198,14 @@ class Core extends events.exports {
66935
67198
  this.prePendingCallPromises.delete(connectId);
66936
67199
  return;
66937
67200
  }
66938
- this.prePendingCallPromises.set(connectId, promise);
67201
+ const previous = this.prePendingCallPromises.get(connectId);
67202
+ const cleanupPromise = previous && previous !== promise
67203
+ ? Promise.all([previous, promise]).then(() => undefined)
67204
+ : promise;
67205
+ this.prePendingCallPromises.set(connectId, cleanupPromise);
67206
+ cleanupPromise.catch(error => {
67207
+ Log.warn('Device cancellation cleanup failed', { errorCode: error === null || error === void 0 ? void 0 : error.errorCode });
67208
+ });
66939
67209
  },
66940
67210
  removePrePendingCallPromise: (connectId, promise) => {
66941
67211
  if (this.prePendingCallPromises.get(connectId) === promise) {