@exodus/hardware-wallets 3.4.0 → 3.4.1

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.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,12 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [3.4.1](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/hardware-wallets@3.4.0...@exodus/hardware-wallets@3.4.1) (2025-11-28)
7
+
8
+ ### Bug Fixes
9
+
10
+ - fix: various trezor and hardware-wallets fixes (#14502)
11
+
6
12
  ## [3.4.0](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/hardware-wallets@3.3.0...@exodus/hardware-wallets@3.4.0) (2025-11-13)
7
13
 
8
14
  ### Features
@@ -18,6 +18,7 @@ export class HardwareWallets {
18
18
  #walletAccounts;
19
19
  #syncedKeysMap = new Map();
20
20
  #signingRequest;
21
+ #isRetrying = false;
21
22
  events = new Emitter();
22
23
  constructor({ assetsModule, ledgerDiscovery, trezorDiscovery, logger, hardwareWalletSigningRequestsAtom, publicKeyStore, wallet, walletAccountsAtom, walletAccounts, }) {
23
24
  this.#assetsModule = assetsModule;
@@ -62,6 +63,11 @@ export class HardwareWallets {
62
63
  this.#logger.warn(`No signing request found for id: ${id}`);
63
64
  return;
64
65
  }
66
+ if (this.#isRetrying) {
67
+ this.#logger.debug(`Retry already in progress for id: ${id}, ignoring duplicate call`);
68
+ return;
69
+ }
70
+ this.#isRetrying = true;
65
71
  try {
66
72
  this.#logger.debug(`Attempting to get selected device for signing request with id: ${id}`);
67
73
  const { device } = await this.#getSelectedDevice();
@@ -79,6 +85,7 @@ export class HardwareWallets {
79
85
  if (['DisconnectedDevice', 'DisconnectedDeviceDuringOperation'].includes(_error.name)) {
80
86
  this.#logger.debug(`Device disconnected during signing request, likely due to app opening: ${id}`, _error);
81
87
  await delay(300);
88
+ this.#isRetrying = false;
82
89
  await this.retrySigningRequest(id);
83
90
  return;
84
91
  }
@@ -93,6 +100,9 @@ export class HardwareWallets {
93
100
  baseAssetName: this.#signingRequest.baseAssetName,
94
101
  });
95
102
  }
103
+ finally {
104
+ this.#isRetrying = false;
105
+ }
96
106
  };
97
107
  cancelSigningRequest = async (id, fromUI) => {
98
108
  const request = this.#signingRequest;
@@ -227,10 +237,10 @@ export class HardwareWallets {
227
237
  getAddress = async ({ assetName, accountIndex, addressIndex, multisigData, displayOnDevice, }) => {
228
238
  const asset = this.#assetsModule.getAsset(assetName);
229
239
  const { device } = await this.#getSelectedDevice();
230
- const supportedPurposes = asset.baseAsset.api.getSupportedPurposes({
240
+ const supportedPurposes = asset.baseAsset.api.getSupportedPurposes?.({
231
241
  compatibilityMode: device.descriptor.manufacturer,
232
242
  isMultisig: !!multisigData,
233
- });
243
+ }) ?? [44];
234
244
  const { derivationPath } = asset.baseAsset.api.getKeyIdentifier({
235
245
  compatibilityMode: device.descriptor.manufacturer,
236
246
  purpose: supportedPurposes[0],
@@ -348,10 +358,10 @@ export class HardwareWallets {
348
358
  continue;
349
359
  }
350
360
  const baseAsset = asset.baseAsset;
351
- const supportedPurposes = baseAsset.api.getSupportedPurposes({
361
+ const supportedPurposes = baseAsset.api.getSupportedPurposes?.({
352
362
  compatibilityMode: source,
353
363
  isMultisig,
354
- });
364
+ }) ?? [44];
355
365
  for (const purpose of supportedPurposes) {
356
366
  const { keyIdentifier, xpub, publicKey, } = (await this.#getXPUB({ device, baseAsset, purpose, accountIndex })) ||
357
367
  (await this.#getPublicKey({ device, baseAsset, purpose, accountIndex }));
@@ -381,6 +391,10 @@ export class HardwareWallets {
381
391
  const { device } = await this.#getSelectedDevice();
382
392
  const source = device.descriptor.manufacturer;
383
393
  const label = source === WalletAccount.LEDGER_SRC ? 'Ledger' : 'Trezor';
394
+ const id = source === WalletAccount.TREZOR_SRC
395
+ ? device.descriptor.internalDescriptor
396
+ :
397
+ randomBytes(32).toString('hex');
384
398
  const { accountIndex, model } = this.#syncedKeysMap.get(syncedKeysId);
385
399
  const walletAccount = new WalletAccount({
386
400
  label: `${label}${accountIndex === 0 ? '' : '_' + accountIndex}`,
@@ -388,7 +402,7 @@ export class HardwareWallets {
388
402
  source,
389
403
  model,
390
404
  index: accountIndex,
391
- id: randomBytes(32).toString('hex'),
405
+ id,
392
406
  isMultisig: !!isMultisig,
393
407
  });
394
408
  const walletAccountName = walletAccount.toString();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/hardware-wallets",
3
- "version": "3.4.0",
3
+ "version": "3.4.1",
4
4
  "description": "An Exodus SDK feature that provides a high level abstraction for interacting with hardware wallet devices",
5
5
  "author": "Exodus Movement, Inc.",
6
6
  "repository": {
@@ -53,5 +53,5 @@
53
53
  "access": "public",
54
54
  "provenance": false
55
55
  },
56
- "gitHead": "781bdadc2bb8d8a749ade2dd01f3f7f62792363d"
56
+ "gitHead": "7c1b8b88571d94cec15b9512e5301922ac1b6017"
57
57
  }