@onekeyfe/hd-core 1.2.0-alpha.42 → 1.2.0-alpha.44

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 (32) hide show
  1. package/__tests__/deviceUploadNft.test.ts +87 -2
  2. package/__tests__/open-wallet-session.test.ts +161 -21
  3. package/__tests__/protocol-v2-ui-lifecycle.test.ts +35 -0
  4. package/__tests__/protocol-v2-unlock-policy.test.ts +110 -0
  5. package/__tests__/protocol-v2.test.ts +71 -13
  6. package/__tests__/protocolV2UiInteraction.test.ts +63 -0
  7. package/dist/api/protocol-v2/DeviceUploadNft.d.ts +1 -0
  8. package/dist/api/protocol-v2/DeviceUploadNft.d.ts.map +1 -1
  9. package/dist/core/index.d.ts.map +1 -1
  10. package/dist/device/Device.d.ts +3 -1
  11. package/dist/device/Device.d.ts.map +1 -1
  12. package/dist/device/DeviceCommands.d.ts +4 -4
  13. package/dist/events/ui-request.d.ts +1 -0
  14. package/dist/events/ui-request.d.ts.map +1 -1
  15. package/dist/index.d.ts +6 -3
  16. package/dist/index.js +174 -45
  17. package/dist/protocols/protocol-v2/uiInteraction.d.ts +4 -1
  18. package/dist/protocols/protocol-v2/uiInteraction.d.ts.map +1 -1
  19. package/dist/protocols/protocol-v2/unlockPolicyRunner.d.ts.map +1 -1
  20. package/dist/protocols/protocol-v2/walletSession.d.ts.map +1 -1
  21. package/dist/utils/pro2Nft.d.ts +2 -0
  22. package/dist/utils/pro2Nft.d.ts.map +1 -1
  23. package/package.json +4 -4
  24. package/src/api/protocol-v2/DeviceUploadNft.ts +25 -2
  25. package/src/core/index.ts +18 -2
  26. package/src/data/messages/messages-protocol-v2.json +15 -0
  27. package/src/device/Device.ts +15 -5
  28. package/src/events/ui-request.ts +1 -0
  29. package/src/protocols/protocol-v2/uiInteraction.ts +20 -6
  30. package/src/protocols/protocol-v2/unlockPolicyRunner.ts +8 -1
  31. package/src/protocols/protocol-v2/walletSession.ts +84 -24
  32. package/src/utils/pro2Nft.ts +51 -0
package/dist/index.js CHANGED
@@ -38095,11 +38095,26 @@ var nested = {
38095
38095
  DeviceSessionError_Busy: 5
38096
38096
  }
38097
38097
  },
38098
+ DeviceSessionSeedDomain: {
38099
+ values: {
38100
+ SeedDomain_Standard: 1,
38101
+ SeedDomain_Cardano: 2
38102
+ }
38103
+ },
38098
38104
  DeviceSessionGet: {
38099
38105
  fields: {
38100
38106
  session_id: {
38101
38107
  type: "bytes",
38102
38108
  id: 1
38109
+ },
38110
+ btc_test_address: {
38111
+ type: "string",
38112
+ id: 2
38113
+ },
38114
+ seed_domains: {
38115
+ rule: "repeated",
38116
+ type: "DeviceSessionSeedDomain",
38117
+ id: 3
38103
38118
  }
38104
38119
  }
38105
38120
  },
@@ -40329,11 +40344,17 @@ const negotiateEventlessWalletSession = (device) => __awaiter(void 0, void 0, vo
40329
40344
  yield device.ensureProtocolV2RuntimeContext();
40330
40345
  });
40331
40346
  const getDeviceSession = (device, request) => __awaiter(void 0, void 0, void 0, function* () { return device.commands.typedCall('DeviceSessionGet', 'DeviceSession', request); });
40347
+ const buildDeviceSessionGetRequest = ({ sessionId, expectedPassphraseState, deriveCardano, } = {}) => (Object.assign(Object.assign(Object.assign({}, (sessionId ? { session_id: sessionId } : {})), (expectedPassphraseState ? { btc_test_address: expectedPassphraseState } : {})), { seed_domains: deriveCardano === undefined
40348
+ ? []
40349
+ : [
40350
+ hdTransport.DeviceSessionSeedDomain.SeedDomain_Standard,
40351
+ ...(deriveCardano ? [hdTransport.DeviceSessionSeedDomain.SeedDomain_Cardano] : []),
40352
+ ] }));
40332
40353
  const askDevicePassphrase = (device, requestPayload) => __awaiter(void 0, void 0, void 0, function* () {
40333
40354
  yield device.commands.typedCall('DeviceSessionAskPassphrase', 'Success', requestPayload);
40334
40355
  yield refreshProtocolV2DeviceStatus(device);
40335
40356
  });
40336
- const selectDeviceSession = (device, expectedPassphraseState) => __awaiter(void 0, void 0, void 0, function* () {
40357
+ const selectDeviceSession = (device, expectedPassphraseState, deriveCardano) => __awaiter(void 0, void 0, void 0, function* () {
40337
40358
  var _a, _b, _c;
40338
40359
  const existsAttachPinUser = ((_a = device.features) === null || _a === void 0 ? void 0 : _a.attachToPinEnabled) === true;
40339
40360
  const metadata = Object.assign({ source: 'wallet-session-coordinator', reason: expectedPassphraseState ? 'session-recovery' : 'open-wallet' }, (expectedPassphraseState ? { expectedPassphraseState } : {}));
@@ -40366,21 +40387,21 @@ const selectDeviceSession = (device, expectedPassphraseState) => __awaiter(void
40366
40387
  emitUiEvent: false,
40367
40388
  interaction: attachPinInteraction,
40368
40389
  });
40369
- return getDeviceSession(device, {});
40390
+ return getDeviceSession(device, buildDeviceSessionGetRequest({ deriveCardano }));
40370
40391
  }
40371
40392
  if (hasHostPassphrase) {
40372
40393
  yield askDevicePassphrase(device, {
40373
40394
  passphrase: hostPassphrase,
40374
40395
  on_device: false,
40375
40396
  });
40376
- return getDeviceSession(device, {});
40397
+ return getDeviceSession(device, buildDeviceSessionGetRequest({ deriveCardano }));
40377
40398
  }
40378
40399
  device.emit(DEVICE.PASSPHRASE_ON_DEVICE, device, Object.assign(Object.assign({}, metadata), (passphraseInteraction ? { interaction: passphraseInteraction } : {})));
40379
40400
  yield askDevicePassphrase(device, { on_device: true });
40380
- return getDeviceSession(device, {});
40401
+ return getDeviceSession(device, buildDeviceSessionGetRequest({ deriveCardano }));
40381
40402
  });
40382
40403
  function getProtocolV2WalletSession(device, options) {
40383
- var _a, _b, _c, _d, _e, _f, _g;
40404
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
40384
40405
  return __awaiter(this, void 0, void 0, function* () {
40385
40406
  const forceWalletSelection = (options === null || options === void 0 ? void 0 : options.forceWalletSelection) === true || (options === null || options === void 0 ? void 0 : options.initSession) === true;
40386
40407
  if (forceWalletSelection) {
@@ -40407,7 +40428,9 @@ function getProtocolV2WalletSession(device, options) {
40407
40428
  : undefined;
40408
40429
  let response;
40409
40430
  let resumed = false;
40410
- let mainWalletSelected = false;
40431
+ let mainPinSelected = (options === null || options === void 0 ? void 0 : options.onlyMainPin) === true &&
40432
+ ((_d = device.features) === null || _d === void 0 ? void 0 : _d.unlocked) === true &&
40433
+ ((_e = device.features) === null || _e === void 0 ? void 0 : _e.unlockedAttachPin) === false;
40411
40434
  const clearCurrentWalletSession = () => {
40412
40435
  var _a;
40413
40436
  if (options === null || options === void 0 ? void 0 : options.onlyMainPin) {
@@ -40425,19 +40448,29 @@ function getProtocolV2WalletSession(device, options) {
40425
40448
  try {
40426
40449
  yield device.lockDevice();
40427
40450
  }
40428
- catch (_h) {
40451
+ catch (_k) {
40429
40452
  }
40430
40453
  clearCurrentWalletSession();
40431
40454
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.DeviceCheckUnlockTypeError);
40432
40455
  });
40433
- const selectMainWallet = (force = false) => __awaiter(this, void 0, void 0, function* () {
40434
- if (force || !mainWalletSelected) {
40456
+ const selectMainPin = (force = false) => __awaiter(this, void 0, void 0, function* () {
40457
+ if (force || !mainPinSelected) {
40435
40458
  yield device.unlockDevice(hdTransport.DeviceSessionPinType.Main, {
40436
40459
  source: 'wallet-session-coordinator',
40437
40460
  reason: expectedPassphraseState ? 'session-recovery' : 'open-wallet',
40438
40461
  deviceOnly: true,
40439
40462
  });
40440
- mainWalletSelected = true;
40463
+ mainPinSelected = true;
40464
+ }
40465
+ });
40466
+ const selectStandardWallet = () => __awaiter(this, void 0, void 0, function* () {
40467
+ var _l;
40468
+ yield selectMainPin();
40469
+ if (((_l = device.features) === null || _l === void 0 ? void 0 : _l.passphraseProtection) === true) {
40470
+ yield askDevicePassphrase(device, {
40471
+ passphrase: '',
40472
+ on_device: false,
40473
+ });
40441
40474
  }
40442
40475
  });
40443
40476
  if (options === null || options === void 0 ? void 0 : options.onlyMainPin) {
@@ -40445,15 +40478,17 @@ function getProtocolV2WalletSession(device, options) {
40445
40478
  if (cachedStandardSession) {
40446
40479
  try {
40447
40480
  if (options === null || options === void 0 ? void 0 : options.selectMainWalletBeforeRestore) {
40448
- yield selectMainWallet();
40481
+ yield selectMainPin();
40449
40482
  }
40450
- response = yield getDeviceSession(device, {
40451
- session_id: cachedStandardSession.sessionId,
40452
- });
40483
+ response = yield getDeviceSession(device, buildDeviceSessionGetRequest({
40484
+ sessionId: cachedStandardSession.sessionId,
40485
+ expectedPassphraseState,
40486
+ deriveCardano: options === null || options === void 0 ? void 0 : options.deriveCardano,
40487
+ }));
40453
40488
  resumed = true;
40454
40489
  }
40455
40490
  catch (error) {
40456
- (_d = device.clearStandardInternalState) === null || _d === void 0 ? void 0 : _d.call(device);
40491
+ (_f = device.clearStandardInternalState) === null || _f === void 0 ? void 0 : _f.call(device);
40457
40492
  if (!isWalletSessionInvalidError(error)) {
40458
40493
  throw error;
40459
40494
  }
@@ -40461,15 +40496,17 @@ function getProtocolV2WalletSession(device, options) {
40461
40496
  }
40462
40497
  }
40463
40498
  if (!response) {
40464
- yield selectMainWallet();
40465
- response = yield getDeviceSession(device, {});
40499
+ yield selectStandardWallet();
40500
+ response = yield getDeviceSession(device, buildDeviceSessionGetRequest({ deriveCardano: options === null || options === void 0 ? void 0 : options.deriveCardano }));
40466
40501
  }
40467
40502
  }
40468
40503
  else if (cachedSessionId && expectedPassphraseState) {
40469
40504
  try {
40470
- response = yield getDeviceSession(device, {
40471
- session_id: cachedSessionId,
40472
- });
40505
+ response = yield getDeviceSession(device, buildDeviceSessionGetRequest({
40506
+ sessionId: cachedSessionId,
40507
+ expectedPassphraseState,
40508
+ deriveCardano: options === null || options === void 0 ? void 0 : options.deriveCardano,
40509
+ }));
40473
40510
  resumed = true;
40474
40511
  }
40475
40512
  catch (error) {
@@ -40482,7 +40519,10 @@ function getProtocolV2WalletSession(device, options) {
40482
40519
  }
40483
40520
  else if (expectedPassphraseState) {
40484
40521
  try {
40485
- response = yield getDeviceSession(device, {});
40522
+ response = yield getDeviceSession(device, buildDeviceSessionGetRequest({
40523
+ expectedPassphraseState,
40524
+ deriveCardano: options === null || options === void 0 ? void 0 : options.deriveCardano,
40525
+ }));
40486
40526
  }
40487
40527
  catch (error) {
40488
40528
  if ((options === null || options === void 0 ? void 0 : options.resumeOnly) || !isWalletSessionInvalidError(error)) {
@@ -40495,7 +40535,7 @@ function getProtocolV2WalletSession(device, options) {
40495
40535
  device.clearInternalState();
40496
40536
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.WalletSessionInvalid);
40497
40537
  }
40498
- response = yield selectDeviceSession(device, expectedPassphraseState);
40538
+ response = yield selectDeviceSession(device, expectedPassphraseState, options === null || options === void 0 ? void 0 : options.deriveCardano);
40499
40539
  }
40500
40540
  let { message } = response;
40501
40541
  try {
@@ -40503,7 +40543,7 @@ function getProtocolV2WalletSession(device, options) {
40503
40543
  }
40504
40544
  catch (error) {
40505
40545
  if (options === null || options === void 0 ? void 0 : options.onlyMainPin) {
40506
- (_e = device.clearStandardInternalState) === null || _e === void 0 ? void 0 : _e.call(device);
40546
+ (_g = device.clearStandardInternalState) === null || _g === void 0 ? void 0 : _g.call(device);
40507
40547
  }
40508
40548
  else {
40509
40549
  device.clearInternalState();
@@ -40518,13 +40558,13 @@ function getProtocolV2WalletSession(device, options) {
40518
40558
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.WalletSessionInvalid);
40519
40559
  }
40520
40560
  if (options === null || options === void 0 ? void 0 : options.onlyMainPin) {
40521
- (_f = device.clearStandardInternalState) === null || _f === void 0 ? void 0 : _f.call(device);
40522
- yield selectMainWallet(true);
40523
- response = yield getDeviceSession(device, {});
40561
+ (_h = device.clearStandardInternalState) === null || _h === void 0 ? void 0 : _h.call(device);
40562
+ yield selectStandardWallet();
40563
+ response = yield getDeviceSession(device, buildDeviceSessionGetRequest({ deriveCardano: options === null || options === void 0 ? void 0 : options.deriveCardano }));
40524
40564
  }
40525
40565
  else {
40526
40566
  device.clearInternalState();
40527
- response = yield selectDeviceSession(device, expectedPassphraseState);
40567
+ response = yield selectDeviceSession(device, expectedPassphraseState, options === null || options === void 0 ? void 0 : options.deriveCardano);
40528
40568
  }
40529
40569
  message = response.message;
40530
40570
  try {
@@ -40532,7 +40572,7 @@ function getProtocolV2WalletSession(device, options) {
40532
40572
  }
40533
40573
  catch (error) {
40534
40574
  if (options === null || options === void 0 ? void 0 : options.onlyMainPin) {
40535
- (_g = device.clearStandardInternalState) === null || _g === void 0 ? void 0 : _g.call(device);
40575
+ (_j = device.clearStandardInternalState) === null || _j === void 0 ? void 0 : _j.call(device);
40536
40576
  }
40537
40577
  else {
40538
40578
  device.clearInternalState();
@@ -40561,7 +40601,7 @@ function getProtocolV2WalletSession(device, options) {
40561
40601
  return {
40562
40602
  passphraseState: message.btc_test_address,
40563
40603
  newSession: message.session_id,
40564
- unlockedAttachPin: mainWalletSelected ? false : undefined,
40604
+ unlockedAttachPin: mainPinSelected ? false : undefined,
40565
40605
  resumed,
40566
40606
  };
40567
40607
  });
@@ -41333,6 +41373,45 @@ const PRO2_NFT_DEFAULT_PACE_MS = 20;
41333
41373
  const PRO2_NFT_DEFAULT_TIMEOUT_MS = 15000;
41334
41374
  const PRO2_NFT_MIN_CHUNK_SIZE = 64;
41335
41375
  const PRO2_NFT_MAX_CHUNK_SIZE = 2048;
41376
+ const PRO2_NFT_MAX_ITEMS = 10;
41377
+ const PRO2_NFT_BASENAME_PATTERN = /^nft-[0-9a-f]{8}-[1-9][0-9]*$/;
41378
+ function parsePro2NftFile(listedPath) {
41379
+ const filename = listedPath.trim().split('/').at(-1);
41380
+ if (!filename)
41381
+ return undefined;
41382
+ let basename;
41383
+ let fileType;
41384
+ if (filename.endsWith('_m.bin')) {
41385
+ basename = filename.slice(0, -'_m.bin'.length);
41386
+ fileType = 'thumbnail';
41387
+ }
41388
+ else if (filename.endsWith('.json')) {
41389
+ basename = filename.slice(0, -'.json'.length);
41390
+ fileType = 'metadata';
41391
+ }
41392
+ else if (filename.endsWith('.bin')) {
41393
+ basename = filename.slice(0, -'.bin'.length);
41394
+ fileType = 'image';
41395
+ }
41396
+ return basename && fileType && PRO2_NFT_BASENAME_PATTERN.test(basename)
41397
+ ? { basename, fileType }
41398
+ : undefined;
41399
+ }
41400
+ function getCompletePro2NftBasenames(childFiles) {
41401
+ var _a, _b;
41402
+ const filesByBasename = new Map();
41403
+ for (const listedPath of (_a = childFiles === null || childFiles === void 0 ? void 0 : childFiles.split('\n')) !== null && _a !== void 0 ? _a : []) {
41404
+ const file = parsePro2NftFile(listedPath);
41405
+ if (file) {
41406
+ const fileTypes = (_b = filesByBasename.get(file.basename)) !== null && _b !== void 0 ? _b : new Set();
41407
+ fileTypes.add(file.fileType);
41408
+ filesByBasename.set(file.basename, fileTypes);
41409
+ }
41410
+ }
41411
+ return new Set([...filesByBasename.entries()]
41412
+ .filter(([, fileTypes]) => fileTypes.size === 3)
41413
+ .map(([basename]) => basename));
41414
+ }
41336
41415
  function utf8Length(value) {
41337
41416
  return new TextEncoder().encode(value).byteLength;
41338
41417
  }
@@ -44637,17 +44716,24 @@ class Device extends events.exports {
44637
44716
  outcome,
44638
44717
  });
44639
44718
  }
44640
- finishProtocolV2UiInteraction(outcome = 'succeeded') {
44719
+ finishProtocolV2UiInteraction(outcome, options) {
44641
44720
  const interaction = this.protocolV2UiInteraction;
44642
- if (!(interaction === null || interaction === void 0 ? void 0 : interaction.opened)) {
44721
+ if (!interaction || (!interaction.opened && !(options === null || options === void 0 ? void 0 : options.ensureMetadata))) {
44643
44722
  this.protocolV2UiInteraction = undefined;
44644
44723
  return undefined;
44645
44724
  }
44646
44725
  const phaseId = `${interaction.interactionId}:phase-${Math.max(interaction.phaseCounter, 1)}`;
44647
- const metadata = this.createProtocolV2UiPhaseMetadata('processing', 'finish', {
44726
+ interaction.opened = true;
44727
+ interaction.sequence += 1;
44728
+ const metadata = {
44729
+ interactionId: interaction.interactionId,
44648
44730
  phaseId,
44649
- outcome,
44650
- });
44731
+ sequence: interaction.sequence,
44732
+ phase: 'processing',
44733
+ transition: 'finish',
44734
+ outcome: outcome !== null && outcome !== void 0 ? outcome : 'succeeded',
44735
+ protocol: 'V2',
44736
+ };
44651
44737
  this.protocolV2UiInteraction = undefined;
44652
44738
  return metadata;
44653
44739
  }
@@ -50423,6 +50509,7 @@ class DeviceUploadWallpaper extends BaseMethod {
50423
50509
  }
50424
50510
 
50425
50511
  const FILESYSTEM_FILE_WRITE_MESSAGE_TYPE = 60805;
50512
+ const FILESYSTEM_DIR_LIST_MESSAGE_TYPE = 60808;
50426
50513
  const NFT_UPDATE_MESSAGE_TYPE = 61500;
50427
50514
  class DeviceUploadNft extends BaseMethod {
50428
50515
  getSupportedProtocols() {
@@ -50451,12 +50538,25 @@ class DeviceUploadNft extends BaseMethod {
50451
50538
  return __awaiter(this, void 0, void 0, function* () {
50452
50539
  const protocolInfo = yield this.device.ensureProtocolV2RuntimeContext();
50453
50540
  const hasFileWrite = supportsProtocolV2Message(protocolInfo, FILESYSTEM_FILE_WRITE_MESSAGE_TYPE);
50541
+ const hasDirList = supportsProtocolV2Message(protocolInfo, FILESYSTEM_DIR_LIST_MESSAGE_TYPE);
50454
50542
  const hasNftUpdate = supportsProtocolV2Message(protocolInfo, NFT_UPDATE_MESSAGE_TYPE);
50455
- if (!hasFileWrite || !hasNftUpdate) {
50543
+ if (!hasFileWrite || !hasDirList || !hasNftUpdate) {
50456
50544
  throw hdShared.createDeviceNotSupportMethodError(this.name, this.device.getCurrentFirmwareType());
50457
50545
  }
50458
50546
  });
50459
50547
  }
50548
+ assertStorageCapacity(basename) {
50549
+ return __awaiter(this, void 0, void 0, function* () {
50550
+ const { message } = yield this.device.commands.typedCall('FilesystemDirList', 'FilesystemDir', { path: PRO2_NFT_DIRECTORY, depth: 1 }, { timeoutMs: this.params.timeoutMs });
50551
+ const existingBasenames = getCompletePro2NftBasenames(message.child_files);
50552
+ if (existingBasenames.size >= PRO2_NFT_MAX_ITEMS && !existingBasenames.has(basename)) {
50553
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.NftStorageLimitReached, undefined, {
50554
+ count: existingBasenames.size,
50555
+ limit: PRO2_NFT_MAX_ITEMS,
50556
+ });
50557
+ }
50558
+ });
50559
+ }
50460
50560
  updateNft(basename) {
50461
50561
  return __awaiter(this, void 0, void 0, function* () {
50462
50562
  const params = { file_name_no_ext: basename };
@@ -50480,6 +50580,9 @@ class DeviceUploadNft extends BaseMethod {
50480
50580
  if (!bundle)
50481
50581
  throw invalidParameter$1('NFT data has not been initialized.');
50482
50582
  yield this.assertCapabilities();
50583
+ this.throwIfAborted();
50584
+ yield this.assertStorageCapacity(bundle.basename);
50585
+ this.throwIfAborted();
50483
50586
  const files = [
50484
50587
  { path: `${PRO2_NFT_DIRECTORY}/${bundle.basename}.bin`, data: bundle.image },
50485
50588
  { path: `${PRO2_NFT_DIRECTORY}/${bundle.basename}_m.bin`, data: bundle.thumbnail },
@@ -50747,17 +50850,23 @@ class ProtocolV2UiInteractionCoordinator {
50747
50850
  resumeMethodInteraction() {
50748
50851
  this.enterMethodInteraction(this.methodInteraction);
50749
50852
  }
50750
- close() {
50853
+ close(options = {}) {
50751
50854
  var _a, _b, _c, _d;
50752
- if (!this.device.isProtocolV2() ||
50753
- (!this.opened && !((_b = (_a = this.device).hasOpenProtocolV2UiInteraction) === null || _b === void 0 ? void 0 : _b.call(_a))) ||
50855
+ if ((!options.protocolV2Operation && !this.device.isProtocolV2()) ||
50856
+ (!options.ensureOperationClose &&
50857
+ !this.opened &&
50858
+ !((_b = (_a = this.device).hasOpenProtocolV2UiInteraction) === null || _b === void 0 ? void 0 : _b.call(_a))) ||
50754
50859
  this.closed)
50755
- return;
50860
+ return false;
50756
50861
  this.closed = true;
50757
- const interaction = (_d = (_c = this.device).finishProtocolV2UiInteraction) === null || _d === void 0 ? void 0 : _d.call(_c);
50862
+ const interaction = (_d = (_c = this.device).finishProtocolV2UiInteraction) === null || _d === void 0 ? void 0 : _d.call(_c, 'succeeded', {
50863
+ ensureMetadata: options.ensureOperationClose,
50864
+ });
50865
+ const device = this.device.toMessageObject();
50758
50866
  this.postMessage(interaction
50759
- ? createUiMessage(UI_REQUEST.CLOSE_UI_WINDOW, interaction)
50867
+ ? createUiMessage(UI_REQUEST.CLOSE_UI_WINDOW, Object.assign(Object.assign({}, interaction), (device ? { device } : {})))
50760
50868
  : createUiMessage(UI_REQUEST.CLOSE_UI_WINDOW));
50869
+ return true;
50761
50870
  }
50762
50871
  emit(type, payload, phase) {
50763
50872
  if (!this.device.isProtocolV2() || this.closed || this.currentPhase === phase)
@@ -50776,7 +50885,7 @@ const createProtocolV2UnlockContext = () => ({
50776
50885
  preflightCompleted: false,
50777
50886
  });
50778
50887
  function runMethodWithUnlockPolicy(method, device, options = {}) {
50779
- var _a, _b;
50888
+ var _a, _b, _c;
50780
50889
  return __awaiter(this, void 0, void 0, function* () {
50781
50890
  const { context = createProtocolV2UnlockContext(), uiCoordinator, afterStatusBeforeUnlock, prepare, run: configuredRun, } = options;
50782
50891
  const run = configuredRun !== null && configuredRun !== void 0 ? configuredRun : (() => method.run());
@@ -50793,7 +50902,11 @@ function runMethodWithUnlockPolicy(method, device, options = {}) {
50793
50902
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 DeviceStatus did not report an explicit unlock state.');
50794
50903
  }
50795
50904
  yield (afterStatusBeforeUnlock === null || afterStatusBeforeUnlock === void 0 ? void 0 : afterStatusBeforeUnlock());
50796
- if (!status.unlocked) {
50905
+ const isStandardWalletRequest = method.unlockPolicy !== 'unlock-before-run' &&
50906
+ method.useDevicePassphraseState &&
50907
+ ((_c = method.payload) === null || _c === void 0 ? void 0 : _c.useEmptyPassphrase) === true;
50908
+ const standardWalletSessionOwnsUnlock = isStandardWalletRequest && status.passphraseProtection === true;
50909
+ if (!status.unlocked && !standardWalletSessionOwnsUnlock) {
50797
50910
  const unlockInteraction = shouldCoordinateUi
50798
50911
  ? uiCoordinator.enterUnlockInteraction(method.name)
50799
50912
  : undefined;
@@ -61031,6 +61144,8 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
61031
61144
  device.on(DEVICE.STATE, onDeviceStateHandler);
61032
61145
  device.on(DEVICE.SELECT_DEVICE_IN_BOOTLOADER_FOR_WEB_DEVICE, onSelectDeviceInBootloaderForWebDeviceHandler);
61033
61146
  const protocolV2UiCoordinator = new ProtocolV2UiInteractionCoordinator(device, postMessage);
61147
+ let protocolV2Operation = false;
61148
+ let protocolV2CloseEmitted = false;
61034
61149
  device.beginProtocolV2UiInteraction();
61035
61150
  device.on(DEVICE.SELECT_DEVICE_FOR_SWITCH_FIRMWARE_WEB_DEVICE, onSelectDeviceForSwitchFirmwareWebDeviceHandler);
61036
61151
  try {
@@ -61041,6 +61156,7 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
61041
61156
  const inner = () => __awaiter(void 0, void 0, void 0, function* () {
61042
61157
  var _j, _k;
61043
61158
  method.assertProtocolSupported(device.getProtocol(), device.getCurrentFirmwareType());
61159
+ protocolV2Operation = device.isProtocolV2();
61044
61160
  const versionRange = device.getCurrentMethodVersionRange(type => method.getVersionRange()[type]);
61045
61161
  const currentFirmwareVersion = (_j = device.getCurrentFirmwareVersionString()) !== null && _j !== void 0 ? _j : '0.0.0';
61046
61162
  const currentBleVersion = (_k = device.getCurrentBLEFirmwareVersionString()) !== null && _k !== void 0 ? _k : '0.0.0';
@@ -61177,7 +61293,12 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
61177
61293
  }
61178
61294
  }
61179
61295
  finally {
61180
- protocolV2UiCoordinator.close();
61296
+ if (isProtocolV2UiEnabled(method)) {
61297
+ protocolV2CloseEmitted = protocolV2UiCoordinator.close({
61298
+ ensureOperationClose: protocolV2Operation,
61299
+ protocolV2Operation,
61300
+ });
61301
+ }
61181
61302
  }
61182
61303
  });
61183
61304
  Log.debug('Call API - Device Run: ', device.mainId);
@@ -61209,7 +61330,15 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
61209
61330
  }
61210
61331
  requestQueue.releaseTask(method.responseID);
61211
61332
  if (isProtocolV2UiEnabled(method)) {
61212
- closePopup();
61333
+ if (!protocolV2CloseEmitted && protocolV2Operation) {
61334
+ protocolV2CloseEmitted = protocolV2UiCoordinator.close({
61335
+ ensureOperationClose: true,
61336
+ protocolV2Operation: true,
61337
+ });
61338
+ }
61339
+ if (!protocolV2CloseEmitted) {
61340
+ closePopup();
61341
+ }
61213
61342
  }
61214
61343
  cleanup();
61215
61344
  if (device) {
@@ -32,7 +32,10 @@ export declare class ProtocolV2UiInteractionCoordinator {
32
32
  enterMethodInteraction(interaction?: ProtocolV2InteractionDescriptor): void;
33
33
  enterUnlockInteraction(method?: string): HardwareUiInteractionMeta | undefined;
34
34
  resumeMethodInteraction(): void;
35
- close(): void;
35
+ close(options?: {
36
+ ensureOperationClose?: boolean;
37
+ protocolV2Operation?: boolean;
38
+ }): boolean;
36
39
  private emit;
37
40
  }
38
41
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"uiInteraction.d.ts","sourceRoot":"","sources":["../../../src/protocols/protocol-v2/uiInteraction.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACnG,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAGlD,MAAM,MAAM,+BAA+B,GAAG;IAC5C,OAAO,EAAE,QAAQ,GAAG,KAAK,CAAC;IAC1B,MAAM,EAAE,kBAAkB,CAAC;IAC3B,MAAM,EACF,YAAY,GACZ,eAAe,GACf,eAAe,GACf,sBAAsB,GACtB,yBAAyB,GACzB,sBAAsB,GACtB,mBAAmB,CAAC;IACxB,UAAU,EAAE,sBAAsB,CAAC;IACnC,UAAU,EAAE,IAAI,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,KAAK,2BAA2B,GAAG;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,uBAAuB,CAAC,EAAE,+BAA+B,CAAC;CAC3D,CAAC;AAEF,KAAK,iBAAiB,GAAG,IAAI,CAAC,MAAM,EAAE,cAAc,GAAG,iBAAiB,CAAC,GACvE,OAAO,CACL,IAAI,CACF,MAAM,EACJ,iCAAiC,GACjC,+BAA+B,GAC/B,gCAAgC,CACnC,CACF,CAAC;AACJ,KAAK,WAAW,GAAG,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;AAElD,eAAO,MAAM,qBAAqB,WAAY;IAAE,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,YAChD,CAAC;AA4DrC,eAAO,MAAM,8BAA8B,WACjC,2BAA2B,KAClC,+BAA+B,GAAG,SAsCpC,CAAC;AAEF,qBAAa,kCAAkC;IAC7C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoB;IAE3C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;IAE1C,OAAO,CAAC,iBAAiB,CAAC,CAAkC;IAE5D,OAAO,CAAC,YAAY,CAAC,CAAS;IAE9B,OAAO,CAAC,MAAM,CAAS;IAEvB,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,EAAE,iBAAiB,EAAE,WAAW,EAAE,WAAW;IAK/D,sBAAsB,CAAC,WAAW,CAAC,EAAE,+BAA+B;IAsBpE,sBAAsB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,yBAAyB,GAAG,SAAS;IAiB9E,uBAAuB;IAIvB,KAAK;IAgBL,OAAO,CAAC,IAAI;CAcb"}
1
+ {"version":3,"file":"uiInteraction.d.ts","sourceRoot":"","sources":["../../../src/protocols/protocol-v2/uiInteraction.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACnG,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAGlD,MAAM,MAAM,+BAA+B,GAAG;IAC5C,OAAO,EAAE,QAAQ,GAAG,KAAK,CAAC;IAC1B,MAAM,EAAE,kBAAkB,CAAC;IAC3B,MAAM,EACF,YAAY,GACZ,eAAe,GACf,eAAe,GACf,sBAAsB,GACtB,yBAAyB,GACzB,sBAAsB,GACtB,mBAAmB,CAAC;IACxB,UAAU,EAAE,sBAAsB,CAAC;IACnC,UAAU,EAAE,IAAI,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,KAAK,2BAA2B,GAAG;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,uBAAuB,CAAC,EAAE,+BAA+B,CAAC;CAC3D,CAAC;AAEF,KAAK,iBAAiB,GAAG,IAAI,CAAC,MAAM,EAAE,cAAc,GAAG,iBAAiB,CAAC,GACvE,OAAO,CACL,IAAI,CACF,MAAM,EACJ,iCAAiC,GACjC,+BAA+B,GAC/B,gCAAgC,CACnC,CACF,CAAC;AACJ,KAAK,WAAW,GAAG,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;AAElD,eAAO,MAAM,qBAAqB,WAAY;IAAE,gBAAgB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,YAChD,CAAC;AA4DrC,eAAO,MAAM,8BAA8B,WACjC,2BAA2B,KAClC,+BAA+B,GAAG,SAsCpC,CAAC;AAEF,qBAAa,kCAAkC;IAC7C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoB;IAE3C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;IAE1C,OAAO,CAAC,iBAAiB,CAAC,CAAkC;IAE5D,OAAO,CAAC,YAAY,CAAC,CAAS;IAE9B,OAAO,CAAC,MAAM,CAAS;IAEvB,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,EAAE,iBAAiB,EAAE,WAAW,EAAE,WAAW;IAK/D,sBAAsB,CAAC,WAAW,CAAC,EAAE,+BAA+B;IAsBpE,sBAAsB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,yBAAyB,GAAG,SAAS;IAiB9E,uBAAuB;IAIvB,KAAK,CACH,OAAO,GAAE;QACP,oBAAoB,CAAC,EAAE,OAAO,CAAC;QAC/B,mBAAmB,CAAC,EAAE,OAAO,CAAC;KAC1B,GACL,OAAO;IAyBV,OAAO,CAAC,IAAI;CAcb"}
@@ -1 +1 @@
1
- {"version":3,"file":"unlockPolicyRunner.d.ts","sourceRoot":"","sources":["../../../src/protocols/protocol-v2/unlockPolicyRunner.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAElD,OAAO,KAAK,EAAE,kCAAkC,EAAE,MAAM,iBAAiB,CAAC;AAI1E,MAAM,MAAM,uBAAuB,GAAG;IACpC,kBAAkB,EAAE,OAAO,CAAC;CAC7B,CAAC;AAEF,eAAO,MAAM,6BAA6B,QAAO,uBAE/C,CAAC;AAEH,KAAK,cAAc,GAAG,IAAI,CACxB,UAAU,EACR,KAAK,GACL,cAAc,GACd,0BAA0B,GAC1B,yBAAyB,GACzB,kBAAkB,GAClB,QAAQ,GACR,SAAS,CACZ,GAAG;IACF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uBAAuB,CAAC,EAAE,uBAAuB,CAAC;CACnD,CAAC;AAEF,KAAK,wBAAwB,GAAG,IAAI,CAClC,kCAAkC,EAClC,wBAAwB,GAAG,wBAAwB,CACpD,CAAC;AAEF,KAAK,gCAAgC,CAAC,CAAC,IAAI;IACzC,OAAO,CAAC,EAAE,uBAAuB,CAAC;IAClC,aAAa,CAAC,EAAE,wBAAwB,CAAC;IACzC,uBAAuB,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,GAAG,CAAC,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC;CACxB,CAAC;AAEF,wBAAsB,yBAAyB,CAAC,CAAC,GAAG,OAAO,EACzD,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,gCAAgC,CAAC,CAAC,CAAM,GAChD,OAAO,CAAC,CAAC,CAAC,CAgEZ"}
1
+ {"version":3,"file":"unlockPolicyRunner.d.ts","sourceRoot":"","sources":["../../../src/protocols/protocol-v2/unlockPolicyRunner.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAElD,OAAO,KAAK,EAAE,kCAAkC,EAAE,MAAM,iBAAiB,CAAC;AAI1E,MAAM,MAAM,uBAAuB,GAAG;IACpC,kBAAkB,EAAE,OAAO,CAAC;CAC7B,CAAC;AAEF,eAAO,MAAM,6BAA6B,QAAO,uBAE/C,CAAC;AAEH,KAAK,cAAc,GAAG,IAAI,CACxB,UAAU,EACR,KAAK,GACL,cAAc,GACd,0BAA0B,GAC1B,yBAAyB,GACzB,kBAAkB,GAClB,QAAQ,GACR,SAAS,CACZ,GAAG;IACF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uBAAuB,CAAC,EAAE,uBAAuB,CAAC;CACnD,CAAC;AAEF,KAAK,wBAAwB,GAAG,IAAI,CAClC,kCAAkC,EAClC,wBAAwB,GAAG,wBAAwB,CACpD,CAAC;AAEF,KAAK,gCAAgC,CAAC,CAAC,IAAI;IACzC,OAAO,CAAC,EAAE,uBAAuB,CAAC;IAClC,aAAa,CAAC,EAAE,wBAAwB,CAAC;IACzC,uBAAuB,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,GAAG,CAAC,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC;CACxB,CAAC;AAEF,wBAAsB,yBAAyB,CAAC,CAAC,GAAG,OAAO,EACzD,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,gCAAgC,CAAC,CAAC,CAAM,GAChD,OAAO,CAAC,CAAC,CAAC,CAuEZ"}
@@ -1 +1 @@
1
- {"version":3,"file":"walletSession.d.ts","sourceRoot":"","sources":["../../../src/protocols/protocol-v2/walletSession.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAuBlD,wBAAsB,6BAA6B,CAAC,MAAM,EAAE,MAAM,0DAGjE;AAED,wBAAsB,6BAA6B,CAAC,MAAM,EAAE,MAAM,qCAGjE;AAED,wBAAsB,qCAAqC,CAAC,MAAM,EAAE,MAAM,oBAgBzE;AA8FD,wBAAsB,0BAA0B,CAC9C,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;IACR,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAE/B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,6BAA6B,CAAC,EAAE,OAAO,CAAC;IACxC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;;;;;GA0LF;AAED,wBAAsB,8BAA8B,CAClD,MAAM,EAAE,MAAM,EACd,uBAAuB,EAAE,MAAM,EAC/B,aAAa,CAAC,EAAE,OAAO;;;;;GAOxB"}
1
+ {"version":3,"file":"walletSession.d.ts","sourceRoot":"","sources":["../../../src/protocols/protocol-v2/walletSession.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAuBlD,wBAAsB,6BAA6B,CAAC,MAAM,EAAE,MAAM,0DAGjE;AAED,wBAAsB,6BAA6B,CAAC,MAAM,EAAE,MAAM,qCAGjE;AAED,wBAAsB,qCAAqC,CAAC,MAAM,EAAE,MAAM,oBAgBzE;AAsHD,wBAAsB,0BAA0B,CAC9C,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;IACR,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAE/B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,6BAA6B,CAAC,EAAE,OAAO,CAAC;IACxC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;;;;;GA8NF;AAED,wBAAsB,8BAA8B,CAClD,MAAM,EAAE,MAAM,EACd,uBAAuB,EAAE,MAAM,EAC/B,aAAa,CAAC,EAAE,OAAO;;;;;GAOxB"}
@@ -8,6 +8,7 @@ export declare const PRO2_NFT_DEFAULT_PACE_MS = 20;
8
8
  export declare const PRO2_NFT_DEFAULT_TIMEOUT_MS = 15000;
9
9
  export declare const PRO2_NFT_MIN_CHUNK_SIZE = 64;
10
10
  export declare const PRO2_NFT_MAX_CHUNK_SIZE = 2048;
11
+ export declare const PRO2_NFT_MAX_ITEMS = 10;
11
12
  export type Pro2NftImage = {
12
13
  width: number;
13
14
  height: number;
@@ -19,6 +20,7 @@ export type Pro2NftBundle = {
19
20
  thumbnail: Uint8Array;
20
21
  metadata: Uint8Array;
21
22
  };
23
+ export declare function getCompletePro2NftBasenames(childFiles?: string): Set<string>;
22
24
  export declare function buildPro2NftBundle(options: {
23
25
  image: Pro2NftImage;
24
26
  thumbnail: Pro2NftImage;
@@ -1 +1 @@
1
- {"version":3,"file":"pro2Nft.d.ts","sourceRoot":"","sources":["../../src/utils/pro2Nft.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,oBAAoB,MAAM,CAAC;AACxC,eAAO,MAAM,qBAAqB,MAAM,CAAC;AACzC,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAC5C,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAC7C,eAAO,MAAM,kBAAkB,cAAc,CAAC;AAC9C,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAC/C,eAAO,MAAM,wBAAwB,KAAK,CAAC;AAC3C,eAAO,MAAM,2BAA2B,QAAS,CAAC;AAClD,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAC1C,eAAO,MAAM,uBAAuB,OAAO,CAAC;AAE5C,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,UAAU,GAAG,WAAW,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,UAAU,CAAC;IAClB,SAAS,EAAE,UAAU,CAAC;IACtB,QAAQ,EAAE,UAAU,CAAC;CACtB,CAAC;AAsBF,wBAAgB,kBAAkB,CAAC,OAAO,EAAE;IAC1C,KAAK,EAAE,YAAY,CAAC;IACpB,SAAS,EAAE,YAAY,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,aAAa,CAkChB"}
1
+ {"version":3,"file":"pro2Nft.d.ts","sourceRoot":"","sources":["../../src/utils/pro2Nft.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,oBAAoB,MAAM,CAAC;AACxC,eAAO,MAAM,qBAAqB,MAAM,CAAC;AACzC,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAC5C,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAC7C,eAAO,MAAM,kBAAkB,cAAc,CAAC;AAC9C,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAC/C,eAAO,MAAM,wBAAwB,KAAK,CAAC;AAC3C,eAAO,MAAM,2BAA2B,QAAS,CAAC;AAClD,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAC1C,eAAO,MAAM,uBAAuB,OAAO,CAAC;AAC5C,eAAO,MAAM,kBAAkB,KAAK,CAAC;AAErC,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,UAAU,GAAG,WAAW,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,UAAU,CAAC;IAClB,SAAS,EAAE,UAAU,CAAC;IACtB,QAAQ,EAAE,UAAU,CAAC;CACtB,CAAC;AAiCF,wBAAgB,2BAA2B,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAiB5E;AAsBD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE;IAC1C,KAAK,EAAE,YAAY,CAAC;IACpB,SAAS,EAAE,YAAY,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB,GAAG,aAAa,CAkChB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/hd-core",
3
- "version": "1.2.0-alpha.42",
3
+ "version": "1.2.0-alpha.44",
4
4
  "description": "Core processes and APIs for communicating with OneKey hardware devices.",
5
5
  "author": "OneKey",
6
6
  "homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
@@ -25,8 +25,8 @@
25
25
  "url": "https://github.com/OneKeyHQ/hardware-js-sdk/issues"
26
26
  },
27
27
  "dependencies": {
28
- "@onekeyfe/hd-shared": "1.2.0-alpha.42",
29
- "@onekeyfe/hd-transport": "1.2.0-alpha.42",
28
+ "@onekeyfe/hd-shared": "1.2.0-alpha.44",
29
+ "@onekeyfe/hd-transport": "1.2.0-alpha.44",
30
30
  "axios": "1.15.2",
31
31
  "bignumber.js": "^9.0.2",
32
32
  "bytebuffer": "^5.0.1",
@@ -44,5 +44,5 @@
44
44
  "@types/w3c-web-usb": "^1.0.10",
45
45
  "@types/web-bluetooth": "^0.0.21"
46
46
  },
47
- "gitHead": "876db04e726acaa06fe51dd78f807df1d101c24d"
47
+ "gitHead": "6de180b61cd4a64f41cf4ffd32eeb8a1cc4e64e7"
48
48
  }
@@ -1,4 +1,4 @@
1
- import { createDeviceNotSupportMethodError } from '@onekeyfe/hd-shared';
1
+ import { ERRORS, HardwareErrorCode, createDeviceNotSupportMethodError } from '@onekeyfe/hd-shared';
2
2
 
3
3
  import { UI_REQUEST, createUiMessage } from '../../events/ui-request';
4
4
  import { supportsProtocolV2Message } from '../../protocols/protocol-v2/features';
@@ -8,10 +8,12 @@ import {
8
8
  PRO2_NFT_DEFAULT_TIMEOUT_MS,
9
9
  PRO2_NFT_DIRECTORY,
10
10
  PRO2_NFT_MAX_CHUNK_SIZE,
11
+ PRO2_NFT_MAX_ITEMS,
11
12
  PRO2_NFT_MIN_CHUNK_SIZE,
12
13
  type Pro2NftBundle,
13
14
  type Pro2NftImage,
14
15
  buildPro2NftBundle,
16
+ getCompletePro2NftBasenames,
15
17
  } from '../../utils/pro2Nft';
16
18
  import { BaseMethod } from '../BaseMethod';
17
19
  import { invalidParameter } from '../helpers/filesystemValidation';
@@ -39,6 +41,7 @@ export type DeviceUploadNftResponse = {
39
41
  };
40
42
 
41
43
  const FILESYSTEM_FILE_WRITE_MESSAGE_TYPE = 60805;
44
+ const FILESYSTEM_DIR_LIST_MESSAGE_TYPE = 60808;
42
45
  const NFT_UPDATE_MESSAGE_TYPE = 61500;
43
46
 
44
47
  export default class DeviceUploadNft extends BaseMethod<DeviceUploadNftParams> {
@@ -88,12 +91,29 @@ export default class DeviceUploadNft extends BaseMethod<DeviceUploadNftParams> {
88
91
  protocolInfo,
89
92
  FILESYSTEM_FILE_WRITE_MESSAGE_TYPE
90
93
  );
94
+ const hasDirList = supportsProtocolV2Message(protocolInfo, FILESYSTEM_DIR_LIST_MESSAGE_TYPE);
91
95
  const hasNftUpdate = supportsProtocolV2Message(protocolInfo, NFT_UPDATE_MESSAGE_TYPE);
92
- if (!hasFileWrite || !hasNftUpdate) {
96
+ if (!hasFileWrite || !hasDirList || !hasNftUpdate) {
93
97
  throw createDeviceNotSupportMethodError(this.name, this.device.getCurrentFirmwareType());
94
98
  }
95
99
  }
96
100
 
101
+ private async assertStorageCapacity(basename: string) {
102
+ const { message } = await this.device.commands.typedCall(
103
+ 'FilesystemDirList',
104
+ 'FilesystemDir',
105
+ { path: PRO2_NFT_DIRECTORY, depth: 1 },
106
+ { timeoutMs: this.params.timeoutMs }
107
+ );
108
+ const existingBasenames = getCompletePro2NftBasenames(message.child_files);
109
+ if (existingBasenames.size >= PRO2_NFT_MAX_ITEMS && !existingBasenames.has(basename)) {
110
+ throw ERRORS.TypedError(HardwareErrorCode.NftStorageLimitReached, undefined, {
111
+ count: existingBasenames.size,
112
+ limit: PRO2_NFT_MAX_ITEMS,
113
+ });
114
+ }
115
+ }
116
+
97
117
  private async updateNft(basename: string) {
98
118
  const params = { file_name_no_ext: basename };
99
119
  const options = { timeoutMs: this.params.timeoutMs };
@@ -113,6 +133,9 @@ export default class DeviceUploadNft extends BaseMethod<DeviceUploadNftParams> {
113
133
  if (!bundle) throw invalidParameter('NFT data has not been initialized.');
114
134
 
115
135
  await this.assertCapabilities();
136
+ this.throwIfAborted();
137
+ await this.assertStorageCapacity(bundle.basename);
138
+ this.throwIfAborted();
116
139
 
117
140
  const files = [
118
141
  { path: `${PRO2_NFT_DIRECTORY}/${bundle.basename}.bin`, data: bundle.image },
package/src/core/index.ts CHANGED
@@ -429,6 +429,8 @@ const onCallDevice = async (
429
429
  );
430
430
 
431
431
  const protocolV2UiCoordinator = new ProtocolV2UiInteractionCoordinator(device, postMessage);
432
+ let protocolV2Operation = false;
433
+ let protocolV2CloseEmitted = false;
432
434
  device.beginProtocolV2UiInteraction();
433
435
  device.on(
434
436
  DEVICE.SELECT_DEVICE_FOR_SWITCH_FIRMWARE_WEB_DEVICE,
@@ -447,6 +449,7 @@ const onCallDevice = async (
447
449
  // Protocol is established from an active device response during acquire/initialize.
448
450
  // Reject unsupported methods before any method-specific device command is sent.
449
451
  method.assertProtocolSupported(device.getProtocol(), device.getCurrentFirmwareType());
452
+ protocolV2Operation = device.isProtocolV2();
450
453
 
451
454
  // check firmware version
452
455
  const versionRange = device.getCurrentMethodVersionRange(
@@ -659,7 +662,12 @@ const onCallDevice = async (
659
662
  throw error;
660
663
  }
661
664
  } finally {
662
- protocolV2UiCoordinator.close();
665
+ if (isProtocolV2UiEnabled(method)) {
666
+ protocolV2CloseEmitted = protocolV2UiCoordinator.close({
667
+ ensureOperationClose: protocolV2Operation,
668
+ protocolV2Operation,
669
+ });
670
+ }
663
671
  }
664
672
  };
665
673
  Log.debug('Call API - Device Run: ', device.mainId);
@@ -714,7 +722,15 @@ const onCallDevice = async (
714
722
  requestQueue.releaseTask(method.responseID);
715
723
 
716
724
  if (isProtocolV2UiEnabled(method)) {
717
- closePopup();
725
+ if (!protocolV2CloseEmitted && protocolV2Operation) {
726
+ protocolV2CloseEmitted = protocolV2UiCoordinator.close({
727
+ ensureOperationClose: true,
728
+ protocolV2Operation: true,
729
+ });
730
+ }
731
+ if (!protocolV2CloseEmitted) {
732
+ closePopup();
733
+ }
718
734
  }
719
735
 
720
736
  cleanup();