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

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 +114 -20
  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 +54 -14
  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 +157 -38
  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 +66 -17
  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 mainWalletSelected = (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,7 +40448,7 @@ 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);
@@ -40447,13 +40470,15 @@ function getProtocolV2WalletSession(device, options) {
40447
40470
  if (options === null || options === void 0 ? void 0 : options.selectMainWalletBeforeRestore) {
40448
40471
  yield selectMainWallet();
40449
40472
  }
40450
- response = yield getDeviceSession(device, {
40451
- session_id: cachedStandardSession.sessionId,
40452
- });
40473
+ response = yield getDeviceSession(device, buildDeviceSessionGetRequest({
40474
+ sessionId: cachedStandardSession.sessionId,
40475
+ expectedPassphraseState,
40476
+ deriveCardano: options === null || options === void 0 ? void 0 : options.deriveCardano,
40477
+ }));
40453
40478
  resumed = true;
40454
40479
  }
40455
40480
  catch (error) {
40456
- (_d = device.clearStandardInternalState) === null || _d === void 0 ? void 0 : _d.call(device);
40481
+ (_f = device.clearStandardInternalState) === null || _f === void 0 ? void 0 : _f.call(device);
40457
40482
  if (!isWalletSessionInvalidError(error)) {
40458
40483
  throw error;
40459
40484
  }
@@ -40462,14 +40487,16 @@ function getProtocolV2WalletSession(device, options) {
40462
40487
  }
40463
40488
  if (!response) {
40464
40489
  yield selectMainWallet();
40465
- response = yield getDeviceSession(device, {});
40490
+ response = yield getDeviceSession(device, buildDeviceSessionGetRequest({ deriveCardano: options === null || options === void 0 ? void 0 : options.deriveCardano }));
40466
40491
  }
40467
40492
  }
40468
40493
  else if (cachedSessionId && expectedPassphraseState) {
40469
40494
  try {
40470
- response = yield getDeviceSession(device, {
40471
- session_id: cachedSessionId,
40472
- });
40495
+ response = yield getDeviceSession(device, buildDeviceSessionGetRequest({
40496
+ sessionId: cachedSessionId,
40497
+ expectedPassphraseState,
40498
+ deriveCardano: options === null || options === void 0 ? void 0 : options.deriveCardano,
40499
+ }));
40473
40500
  resumed = true;
40474
40501
  }
40475
40502
  catch (error) {
@@ -40482,7 +40509,10 @@ function getProtocolV2WalletSession(device, options) {
40482
40509
  }
40483
40510
  else if (expectedPassphraseState) {
40484
40511
  try {
40485
- response = yield getDeviceSession(device, {});
40512
+ response = yield getDeviceSession(device, buildDeviceSessionGetRequest({
40513
+ expectedPassphraseState,
40514
+ deriveCardano: options === null || options === void 0 ? void 0 : options.deriveCardano,
40515
+ }));
40486
40516
  }
40487
40517
  catch (error) {
40488
40518
  if ((options === null || options === void 0 ? void 0 : options.resumeOnly) || !isWalletSessionInvalidError(error)) {
@@ -40495,7 +40525,7 @@ function getProtocolV2WalletSession(device, options) {
40495
40525
  device.clearInternalState();
40496
40526
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.WalletSessionInvalid);
40497
40527
  }
40498
- response = yield selectDeviceSession(device, expectedPassphraseState);
40528
+ response = yield selectDeviceSession(device, expectedPassphraseState, options === null || options === void 0 ? void 0 : options.deriveCardano);
40499
40529
  }
40500
40530
  let { message } = response;
40501
40531
  try {
@@ -40503,7 +40533,7 @@ function getProtocolV2WalletSession(device, options) {
40503
40533
  }
40504
40534
  catch (error) {
40505
40535
  if (options === null || options === void 0 ? void 0 : options.onlyMainPin) {
40506
- (_e = device.clearStandardInternalState) === null || _e === void 0 ? void 0 : _e.call(device);
40536
+ (_g = device.clearStandardInternalState) === null || _g === void 0 ? void 0 : _g.call(device);
40507
40537
  }
40508
40538
  else {
40509
40539
  device.clearInternalState();
@@ -40518,13 +40548,13 @@ function getProtocolV2WalletSession(device, options) {
40518
40548
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.WalletSessionInvalid);
40519
40549
  }
40520
40550
  if (options === null || options === void 0 ? void 0 : options.onlyMainPin) {
40521
- (_f = device.clearStandardInternalState) === null || _f === void 0 ? void 0 : _f.call(device);
40551
+ (_h = device.clearStandardInternalState) === null || _h === void 0 ? void 0 : _h.call(device);
40522
40552
  yield selectMainWallet(true);
40523
- response = yield getDeviceSession(device, {});
40553
+ response = yield getDeviceSession(device, buildDeviceSessionGetRequest({ deriveCardano: options === null || options === void 0 ? void 0 : options.deriveCardano }));
40524
40554
  }
40525
40555
  else {
40526
40556
  device.clearInternalState();
40527
- response = yield selectDeviceSession(device, expectedPassphraseState);
40557
+ response = yield selectDeviceSession(device, expectedPassphraseState, options === null || options === void 0 ? void 0 : options.deriveCardano);
40528
40558
  }
40529
40559
  message = response.message;
40530
40560
  try {
@@ -40532,7 +40562,7 @@ function getProtocolV2WalletSession(device, options) {
40532
40562
  }
40533
40563
  catch (error) {
40534
40564
  if (options === null || options === void 0 ? void 0 : options.onlyMainPin) {
40535
- (_g = device.clearStandardInternalState) === null || _g === void 0 ? void 0 : _g.call(device);
40565
+ (_j = device.clearStandardInternalState) === null || _j === void 0 ? void 0 : _j.call(device);
40536
40566
  }
40537
40567
  else {
40538
40568
  device.clearInternalState();
@@ -41333,6 +41363,45 @@ const PRO2_NFT_DEFAULT_PACE_MS = 20;
41333
41363
  const PRO2_NFT_DEFAULT_TIMEOUT_MS = 15000;
41334
41364
  const PRO2_NFT_MIN_CHUNK_SIZE = 64;
41335
41365
  const PRO2_NFT_MAX_CHUNK_SIZE = 2048;
41366
+ const PRO2_NFT_MAX_ITEMS = 10;
41367
+ const PRO2_NFT_BASENAME_PATTERN = /^nft-[0-9a-f]{8}-[1-9][0-9]*$/;
41368
+ function parsePro2NftFile(listedPath) {
41369
+ const filename = listedPath.trim().split('/').at(-1);
41370
+ if (!filename)
41371
+ return undefined;
41372
+ let basename;
41373
+ let fileType;
41374
+ if (filename.endsWith('_m.bin')) {
41375
+ basename = filename.slice(0, -'_m.bin'.length);
41376
+ fileType = 'thumbnail';
41377
+ }
41378
+ else if (filename.endsWith('.json')) {
41379
+ basename = filename.slice(0, -'.json'.length);
41380
+ fileType = 'metadata';
41381
+ }
41382
+ else if (filename.endsWith('.bin')) {
41383
+ basename = filename.slice(0, -'.bin'.length);
41384
+ fileType = 'image';
41385
+ }
41386
+ return basename && fileType && PRO2_NFT_BASENAME_PATTERN.test(basename)
41387
+ ? { basename, fileType }
41388
+ : undefined;
41389
+ }
41390
+ function getCompletePro2NftBasenames(childFiles) {
41391
+ var _a, _b;
41392
+ const filesByBasename = new Map();
41393
+ for (const listedPath of (_a = childFiles === null || childFiles === void 0 ? void 0 : childFiles.split('\n')) !== null && _a !== void 0 ? _a : []) {
41394
+ const file = parsePro2NftFile(listedPath);
41395
+ if (file) {
41396
+ const fileTypes = (_b = filesByBasename.get(file.basename)) !== null && _b !== void 0 ? _b : new Set();
41397
+ fileTypes.add(file.fileType);
41398
+ filesByBasename.set(file.basename, fileTypes);
41399
+ }
41400
+ }
41401
+ return new Set([...filesByBasename.entries()]
41402
+ .filter(([, fileTypes]) => fileTypes.size === 3)
41403
+ .map(([basename]) => basename));
41404
+ }
41336
41405
  function utf8Length(value) {
41337
41406
  return new TextEncoder().encode(value).byteLength;
41338
41407
  }
@@ -44637,17 +44706,24 @@ class Device extends events.exports {
44637
44706
  outcome,
44638
44707
  });
44639
44708
  }
44640
- finishProtocolV2UiInteraction(outcome = 'succeeded') {
44709
+ finishProtocolV2UiInteraction(outcome, options) {
44641
44710
  const interaction = this.protocolV2UiInteraction;
44642
- if (!(interaction === null || interaction === void 0 ? void 0 : interaction.opened)) {
44711
+ if (!interaction || (!interaction.opened && !(options === null || options === void 0 ? void 0 : options.ensureMetadata))) {
44643
44712
  this.protocolV2UiInteraction = undefined;
44644
44713
  return undefined;
44645
44714
  }
44646
44715
  const phaseId = `${interaction.interactionId}:phase-${Math.max(interaction.phaseCounter, 1)}`;
44647
- const metadata = this.createProtocolV2UiPhaseMetadata('processing', 'finish', {
44716
+ interaction.opened = true;
44717
+ interaction.sequence += 1;
44718
+ const metadata = {
44719
+ interactionId: interaction.interactionId,
44648
44720
  phaseId,
44649
- outcome,
44650
- });
44721
+ sequence: interaction.sequence,
44722
+ phase: 'processing',
44723
+ transition: 'finish',
44724
+ outcome: outcome !== null && outcome !== void 0 ? outcome : 'succeeded',
44725
+ protocol: 'V2',
44726
+ };
44651
44727
  this.protocolV2UiInteraction = undefined;
44652
44728
  return metadata;
44653
44729
  }
@@ -50423,6 +50499,7 @@ class DeviceUploadWallpaper extends BaseMethod {
50423
50499
  }
50424
50500
 
50425
50501
  const FILESYSTEM_FILE_WRITE_MESSAGE_TYPE = 60805;
50502
+ const FILESYSTEM_DIR_LIST_MESSAGE_TYPE = 60808;
50426
50503
  const NFT_UPDATE_MESSAGE_TYPE = 61500;
50427
50504
  class DeviceUploadNft extends BaseMethod {
50428
50505
  getSupportedProtocols() {
@@ -50451,12 +50528,25 @@ class DeviceUploadNft extends BaseMethod {
50451
50528
  return __awaiter(this, void 0, void 0, function* () {
50452
50529
  const protocolInfo = yield this.device.ensureProtocolV2RuntimeContext();
50453
50530
  const hasFileWrite = supportsProtocolV2Message(protocolInfo, FILESYSTEM_FILE_WRITE_MESSAGE_TYPE);
50531
+ const hasDirList = supportsProtocolV2Message(protocolInfo, FILESYSTEM_DIR_LIST_MESSAGE_TYPE);
50454
50532
  const hasNftUpdate = supportsProtocolV2Message(protocolInfo, NFT_UPDATE_MESSAGE_TYPE);
50455
- if (!hasFileWrite || !hasNftUpdate) {
50533
+ if (!hasFileWrite || !hasDirList || !hasNftUpdate) {
50456
50534
  throw hdShared.createDeviceNotSupportMethodError(this.name, this.device.getCurrentFirmwareType());
50457
50535
  }
50458
50536
  });
50459
50537
  }
50538
+ assertStorageCapacity(basename) {
50539
+ return __awaiter(this, void 0, void 0, function* () {
50540
+ const { message } = yield this.device.commands.typedCall('FilesystemDirList', 'FilesystemDir', { path: PRO2_NFT_DIRECTORY, depth: 1 }, { timeoutMs: this.params.timeoutMs });
50541
+ const existingBasenames = getCompletePro2NftBasenames(message.child_files);
50542
+ if (existingBasenames.size >= PRO2_NFT_MAX_ITEMS && !existingBasenames.has(basename)) {
50543
+ throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.NftStorageLimitReached, undefined, {
50544
+ count: existingBasenames.size,
50545
+ limit: PRO2_NFT_MAX_ITEMS,
50546
+ });
50547
+ }
50548
+ });
50549
+ }
50460
50550
  updateNft(basename) {
50461
50551
  return __awaiter(this, void 0, void 0, function* () {
50462
50552
  const params = { file_name_no_ext: basename };
@@ -50480,6 +50570,9 @@ class DeviceUploadNft extends BaseMethod {
50480
50570
  if (!bundle)
50481
50571
  throw invalidParameter$1('NFT data has not been initialized.');
50482
50572
  yield this.assertCapabilities();
50573
+ this.throwIfAborted();
50574
+ yield this.assertStorageCapacity(bundle.basename);
50575
+ this.throwIfAborted();
50483
50576
  const files = [
50484
50577
  { path: `${PRO2_NFT_DIRECTORY}/${bundle.basename}.bin`, data: bundle.image },
50485
50578
  { path: `${PRO2_NFT_DIRECTORY}/${bundle.basename}_m.bin`, data: bundle.thumbnail },
@@ -50747,17 +50840,23 @@ class ProtocolV2UiInteractionCoordinator {
50747
50840
  resumeMethodInteraction() {
50748
50841
  this.enterMethodInteraction(this.methodInteraction);
50749
50842
  }
50750
- close() {
50843
+ close(options = {}) {
50751
50844
  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))) ||
50845
+ if ((!options.protocolV2Operation && !this.device.isProtocolV2()) ||
50846
+ (!options.ensureOperationClose &&
50847
+ !this.opened &&
50848
+ !((_b = (_a = this.device).hasOpenProtocolV2UiInteraction) === null || _b === void 0 ? void 0 : _b.call(_a))) ||
50754
50849
  this.closed)
50755
- return;
50850
+ return false;
50756
50851
  this.closed = true;
50757
- const interaction = (_d = (_c = this.device).finishProtocolV2UiInteraction) === null || _d === void 0 ? void 0 : _d.call(_c);
50852
+ const interaction = (_d = (_c = this.device).finishProtocolV2UiInteraction) === null || _d === void 0 ? void 0 : _d.call(_c, 'succeeded', {
50853
+ ensureMetadata: options.ensureOperationClose,
50854
+ });
50855
+ const device = this.device.toMessageObject();
50758
50856
  this.postMessage(interaction
50759
- ? createUiMessage(UI_REQUEST.CLOSE_UI_WINDOW, interaction)
50857
+ ? createUiMessage(UI_REQUEST.CLOSE_UI_WINDOW, Object.assign(Object.assign({}, interaction), (device ? { device } : {})))
50760
50858
  : createUiMessage(UI_REQUEST.CLOSE_UI_WINDOW));
50859
+ return true;
50761
50860
  }
50762
50861
  emit(type, payload, phase) {
50763
50862
  if (!this.device.isProtocolV2() || this.closed || this.currentPhase === phase)
@@ -50776,7 +50875,7 @@ const createProtocolV2UnlockContext = () => ({
50776
50875
  preflightCompleted: false,
50777
50876
  });
50778
50877
  function runMethodWithUnlockPolicy(method, device, options = {}) {
50779
- var _a, _b;
50878
+ var _a, _b, _c;
50780
50879
  return __awaiter(this, void 0, void 0, function* () {
50781
50880
  const { context = createProtocolV2UnlockContext(), uiCoordinator, afterStatusBeforeUnlock, prepare, run: configuredRun, } = options;
50782
50881
  const run = configuredRun !== null && configuredRun !== void 0 ? configuredRun : (() => method.run());
@@ -50793,7 +50892,11 @@ function runMethodWithUnlockPolicy(method, device, options = {}) {
50793
50892
  throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.RuntimeError, 'Protocol V2 DeviceStatus did not report an explicit unlock state.');
50794
50893
  }
50795
50894
  yield (afterStatusBeforeUnlock === null || afterStatusBeforeUnlock === void 0 ? void 0 : afterStatusBeforeUnlock());
50796
- if (!status.unlocked) {
50895
+ const isStandardWalletRequest = method.unlockPolicy !== 'unlock-before-run' &&
50896
+ method.useDevicePassphraseState &&
50897
+ ((_c = method.payload) === null || _c === void 0 ? void 0 : _c.useEmptyPassphrase) === true;
50898
+ const standardWalletSessionOwnsUnlock = isStandardWalletRequest && status.passphraseProtection === true;
50899
+ if (!status.unlocked && !standardWalletSessionOwnsUnlock) {
50797
50900
  const unlockInteraction = shouldCoordinateUi
50798
50901
  ? uiCoordinator.enterUnlockInteraction(method.name)
50799
50902
  : undefined;
@@ -61031,6 +61134,8 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
61031
61134
  device.on(DEVICE.STATE, onDeviceStateHandler);
61032
61135
  device.on(DEVICE.SELECT_DEVICE_IN_BOOTLOADER_FOR_WEB_DEVICE, onSelectDeviceInBootloaderForWebDeviceHandler);
61033
61136
  const protocolV2UiCoordinator = new ProtocolV2UiInteractionCoordinator(device, postMessage);
61137
+ let protocolV2Operation = false;
61138
+ let protocolV2CloseEmitted = false;
61034
61139
  device.beginProtocolV2UiInteraction();
61035
61140
  device.on(DEVICE.SELECT_DEVICE_FOR_SWITCH_FIRMWARE_WEB_DEVICE, onSelectDeviceForSwitchFirmwareWebDeviceHandler);
61036
61141
  try {
@@ -61041,6 +61146,7 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
61041
61146
  const inner = () => __awaiter(void 0, void 0, void 0, function* () {
61042
61147
  var _j, _k;
61043
61148
  method.assertProtocolSupported(device.getProtocol(), device.getCurrentFirmwareType());
61149
+ protocolV2Operation = device.isProtocolV2();
61044
61150
  const versionRange = device.getCurrentMethodVersionRange(type => method.getVersionRange()[type]);
61045
61151
  const currentFirmwareVersion = (_j = device.getCurrentFirmwareVersionString()) !== null && _j !== void 0 ? _j : '0.0.0';
61046
61152
  const currentBleVersion = (_k = device.getCurrentBLEFirmwareVersionString()) !== null && _k !== void 0 ? _k : '0.0.0';
@@ -61177,7 +61283,12 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
61177
61283
  }
61178
61284
  }
61179
61285
  finally {
61180
- protocolV2UiCoordinator.close();
61286
+ if (isProtocolV2UiEnabled(method)) {
61287
+ protocolV2CloseEmitted = protocolV2UiCoordinator.close({
61288
+ ensureOperationClose: protocolV2Operation,
61289
+ protocolV2Operation,
61290
+ });
61291
+ }
61181
61292
  }
61182
61293
  });
61183
61294
  Log.debug('Call API - Device Run: ', device.mainId);
@@ -61209,7 +61320,15 @@ const onCallDevice = (context, message, method) => __awaiter(void 0, void 0, voi
61209
61320
  }
61210
61321
  requestQueue.releaseTask(method.responseID);
61211
61322
  if (isProtocolV2UiEnabled(method)) {
61212
- closePopup();
61323
+ if (!protocolV2CloseEmitted && protocolV2Operation) {
61324
+ protocolV2CloseEmitted = protocolV2UiCoordinator.close({
61325
+ ensureOperationClose: true,
61326
+ protocolV2Operation: true,
61327
+ });
61328
+ }
61329
+ if (!protocolV2CloseEmitted) {
61330
+ closePopup();
61331
+ }
61213
61332
  }
61214
61333
  cleanup();
61215
61334
  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;;;;;GAmNF;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.43",
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.43",
29
+ "@onekeyfe/hd-transport": "1.2.0-alpha.43",
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": "2ea7c9d60472502a272a57f808aed3773ccd84c4"
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();
@@ -12244,11 +12244,26 @@
12244
12244
  "DeviceSessionError_Busy": 5
12245
12245
  }
12246
12246
  },
12247
+ "DeviceSessionSeedDomain": {
12248
+ "values": {
12249
+ "SeedDomain_Standard": 1,
12250
+ "SeedDomain_Cardano": 2
12251
+ }
12252
+ },
12247
12253
  "DeviceSessionGet": {
12248
12254
  "fields": {
12249
12255
  "session_id": {
12250
12256
  "type": "bytes",
12251
12257
  "id": 1
12258
+ },
12259
+ "btc_test_address": {
12260
+ "type": "string",
12261
+ "id": 2
12262
+ },
12263
+ "seed_domains": {
12264
+ "rule": "repeated",
12265
+ "type": "DeviceSessionSeedDomain",
12266
+ "id": 3
12252
12267
  }
12253
12268
  }
12254
12269
  },