@exodus/hardware-wallets 3.5.0 → 3.6.0
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 +6 -0
- package/lib/api/index.d.ts +1 -1
- package/lib/api/index.js +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/module/hardware-wallets.d.ts +2 -2
- package/lib/module/hardware-wallets.js +20 -25
- package/lib/module/interfaces.d.ts +5 -1
- package/package.json +3 -3
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.6.0](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/hardware-wallets@3.5.0...@exodus/hardware-wallets@3.6.0) (2026-01-21)
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
- feat: trezor passphrase support (#14965)
|
|
11
|
+
|
|
6
12
|
## [3.5.0](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/hardware-wallets@3.4.0...@exodus/hardware-wallets@3.5.0) (2025-12-11)
|
|
7
13
|
|
|
8
14
|
### Features
|
package/lib/api/index.d.ts
CHANGED
|
@@ -16,7 +16,6 @@ declare const hardwareWalletsApiDefinition: {
|
|
|
16
16
|
listUseableAssetNames: () => Promise<string[]>;
|
|
17
17
|
scanForDevices: (deviceType?: import("libraries/hw-common/lib/types.js").HardwareWalletManufacturer) => Promise<void>;
|
|
18
18
|
canAccessAsset: ({ assetName }: import("../module/interfaces.js").CanAccessAssetParams) => Promise<boolean>;
|
|
19
|
-
ensureApplicationIsOpened: ({ assetName }: import("../module/interfaces.js").EnsureApplicationIsOpenedParams) => Promise<void>;
|
|
20
19
|
scan: ({ assetName, accountIndexes, addressLimit, addressOffset, }: import("../module/interfaces.js").ScanParams) => Promise<import("../module/interfaces.js").ScanResult>;
|
|
21
20
|
sync: ({ accountIndex: index, isMultisig }?: import("../module/interfaces.js").SyncParams) => Promise<import("../module/interfaces.js").SyncedKeysId>;
|
|
22
21
|
addPublicKeysToWalletAccount: ({ walletAccount, syncedKeysId }: import("../module/interfaces.js").StoreSyncedKeysParams) => Promise<void>;
|
|
@@ -25,6 +24,7 @@ declare const hardwareWalletsApiDefinition: {
|
|
|
25
24
|
cancelSigningRequest: (id: string, fromUI: boolean) => Promise<void>;
|
|
26
25
|
submitPairingCode: ({ code }: import("../module/interfaces.js").ProcessPairingCodeParams) => Promise<any>;
|
|
27
26
|
clearPairingRequest: () => () => Promise<void>;
|
|
27
|
+
setPassphraseMode: ({ enabled }: import("../module/interfaces.js").SetPassphraseModeParams) => Promise<void>;
|
|
28
28
|
};
|
|
29
29
|
};
|
|
30
30
|
readonly dependencies: readonly ["hardwareWallets", "txLogMonitors", "restoreProgressTracker"];
|
package/lib/api/index.js
CHANGED
|
@@ -23,7 +23,6 @@ const createHardwareWalletsApi = ({ hardwareWallets, restoreProgressTracker, txL
|
|
|
23
23
|
listUseableAssetNames: hardwareWallets.listUseableAssetNames,
|
|
24
24
|
scanForDevices: hardwareWallets.scanForDevices,
|
|
25
25
|
canAccessAsset: hardwareWallets.canAccessAsset,
|
|
26
|
-
ensureApplicationIsOpened: hardwareWallets.ensureApplicationIsOpened,
|
|
27
26
|
scan: hardwareWallets.scan,
|
|
28
27
|
sync: hardwareWallets.sync,
|
|
29
28
|
addPublicKeysToWalletAccount: hardwareWallets.addPublicKeysToWalletAccount,
|
|
@@ -32,6 +31,7 @@ const createHardwareWalletsApi = ({ hardwareWallets, restoreProgressTracker, txL
|
|
|
32
31
|
cancelSigningRequest: hardwareWallets.cancelSigningRequest,
|
|
33
32
|
submitPairingCode: hardwareWallets.submitPairingCode,
|
|
34
33
|
clearPairingRequest: () => hardwareWallets.clearPairingRequest,
|
|
34
|
+
setPassphraseMode: hardwareWallets.setPassphraseMode,
|
|
35
35
|
},
|
|
36
36
|
};
|
|
37
37
|
};
|
package/lib/index.d.ts
CHANGED
|
@@ -19,7 +19,6 @@ declare const hardwareWallets: () => {
|
|
|
19
19
|
listUseableAssetNames: () => Promise<string[]>;
|
|
20
20
|
scanForDevices: (deviceType?: import("libraries/hw-common/lib/types.js").HardwareWalletManufacturer) => Promise<void>;
|
|
21
21
|
canAccessAsset: ({ assetName }: import("./module/interfaces.js").CanAccessAssetParams) => Promise<boolean>;
|
|
22
|
-
ensureApplicationIsOpened: ({ assetName }: import("./module/interfaces.js").EnsureApplicationIsOpenedParams) => Promise<void>;
|
|
23
22
|
scan: ({ assetName, accountIndexes, addressLimit, addressOffset, }: import("./module/interfaces.js").ScanParams) => Promise<import("./module/interfaces.js").ScanResult>;
|
|
24
23
|
sync: ({ accountIndex: index, isMultisig }?: import("./module/interfaces.js").SyncParams) => Promise<import("./module/interfaces.js").SyncedKeysId>;
|
|
25
24
|
addPublicKeysToWalletAccount: ({ walletAccount, syncedKeysId }: import("./module/interfaces.js").StoreSyncedKeysParams) => Promise<void>;
|
|
@@ -28,6 +27,7 @@ declare const hardwareWallets: () => {
|
|
|
28
27
|
cancelSigningRequest: (id: string, fromUI: boolean) => Promise<void>;
|
|
29
28
|
submitPairingCode: ({ code }: import("./module/interfaces.js").ProcessPairingCodeParams) => Promise<any>;
|
|
30
29
|
clearPairingRequest: () => () => Promise<void>;
|
|
30
|
+
setPassphraseMode: ({ enabled }: import("./module/interfaces.js").SetPassphraseModeParams) => Promise<void>;
|
|
31
31
|
};
|
|
32
32
|
};
|
|
33
33
|
readonly dependencies: readonly ["hardwareWallets", "txLogMonitors", "restoreProgressTracker"];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { WalletAccount } from '@exodus/models';
|
|
2
2
|
import Emitter from '@exodus/wild-emitter';
|
|
3
|
-
import type { HardwareSignerProvider, CanAccessAssetParams, CreateParams, StoreSyncedKeysParams, ScanParams, SyncParams,
|
|
3
|
+
import type { HardwareSignerProvider, CanAccessAssetParams, CreateParams, StoreSyncedKeysParams, ScanParams, SyncParams, SignTransactionParams, ScanResult, SyncedKeysId, GetAddressParams, RequireDeviceForParams, ProcessPairingCodeParams, SigningRequestState, SetPassphraseModeParams } from './interfaces.js';
|
|
4
4
|
import type { HardwareWalletDiscovery, HardwareWalletManufacturer, SignMessageParams } from '@exodus/hw-common';
|
|
5
5
|
import type { Atom } from '@exodus/atoms';
|
|
6
6
|
import type { IPublicKeyStore } from '@exodus/public-key-provider/lib/module/store/types';
|
|
@@ -38,7 +38,6 @@ export declare class HardwareWallets implements HardwareSignerProvider {
|
|
|
38
38
|
}[]>;
|
|
39
39
|
canAccessAsset: ({ assetName }: CanAccessAssetParams) => Promise<boolean>;
|
|
40
40
|
listUseableAssetNames: () => Promise<string[]>;
|
|
41
|
-
ensureApplicationIsOpened: ({ assetName }: EnsureApplicationIsOpenedParams) => Promise<void>;
|
|
42
41
|
getAddress: ({ assetName, accountIndex, addressIndex, multisigData, displayOnDevice, }: GetAddressParams) => Promise<string>;
|
|
43
42
|
scan: ({ assetName, accountIndexes, addressLimit, addressOffset, }: ScanParams) => Promise<ScanResult>;
|
|
44
43
|
sync: ({ accountIndex: index, isMultisig }?: SyncParams) => Promise<SyncedKeysId>;
|
|
@@ -46,6 +45,7 @@ export declare class HardwareWallets implements HardwareSignerProvider {
|
|
|
46
45
|
create: ({ syncedKeysId, isMultisig }: CreateParams) => Promise<WalletAccount>;
|
|
47
46
|
clearPairingRequest: () => Promise<void>;
|
|
48
47
|
submitPairingCode: ({ code }: ProcessPairingCodeParams) => Promise<any>;
|
|
48
|
+
setPassphraseMode: ({ enabled }: SetPassphraseModeParams) => Promise<void>;
|
|
49
49
|
requireDeviceFor: ({ walletAccount }: RequireDeviceForParams) => Promise<{
|
|
50
50
|
signTransaction: ({ baseAssetName, unsignedTx, walletAccount, multisigData, }: SignTransactionParams) => Promise<any>;
|
|
51
51
|
signMessage: ({ assetName, derivationPath, message }: SignMessageParams) => Promise<any>;
|
|
@@ -3,7 +3,7 @@ import { WalletAccount } from '@exodus/models';
|
|
|
3
3
|
import Emitter from '@exodus/wild-emitter';
|
|
4
4
|
import { randomBytes } from '@exodus/crypto/randomBytes';
|
|
5
5
|
import delay from 'delay';
|
|
6
|
-
import { DeviceUninitializedError, NoDeviceFoundError, UserRefusedError } from '@exodus/hw-common';
|
|
6
|
+
import { DeviceUninitializedError, NoDeviceFoundError, HardwareWalletManufacturerMismatchError, UserRefusedError, } from '@exodus/hw-common';
|
|
7
7
|
import restrictConcurrency from 'make-concurrent';
|
|
8
8
|
import pDefer from 'p-defer';
|
|
9
9
|
export class HardwareWallets {
|
|
@@ -20,6 +20,15 @@ export class HardwareWallets {
|
|
|
20
20
|
#signingRequest;
|
|
21
21
|
#isRetrying = false;
|
|
22
22
|
events = new Emitter();
|
|
23
|
+
#requireTrezorDevice = (device) => {
|
|
24
|
+
if (device.descriptor.manufacturer !== WalletAccount.TREZOR_SRC) {
|
|
25
|
+
throw new HardwareWalletManufacturerMismatchError({
|
|
26
|
+
expected: WalletAccount.TREZOR_SRC,
|
|
27
|
+
actual: String(device.descriptor.manufacturer),
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
return device;
|
|
31
|
+
};
|
|
23
32
|
constructor({ assetsModule, ledgerDiscovery, trezorDiscovery, logger, hardwareWalletSigningRequestsAtom, publicKeyStore, wallet, walletAccountsAtom, walletAccounts, }) {
|
|
24
33
|
this.#assetsModule = assetsModule;
|
|
25
34
|
this.#ledgerDiscovery = ledgerDiscovery;
|
|
@@ -168,7 +177,7 @@ export class HardwareWallets {
|
|
|
168
177
|
baseAssetName,
|
|
169
178
|
scenario,
|
|
170
179
|
});
|
|
171
|
-
await device.
|
|
180
|
+
await device.ensureDeviceReady({ baseAssetName, walletAccount });
|
|
172
181
|
return sign({ device });
|
|
173
182
|
},
|
|
174
183
|
resolve: deferred.resolve,
|
|
@@ -256,23 +265,6 @@ export class HardwareWallets {
|
|
|
256
265
|
const { device } = await this.#getSelectedDevice();
|
|
257
266
|
return device.listUseableAssetNames();
|
|
258
267
|
};
|
|
259
|
-
ensureApplicationIsOpened = async ({ assetName }) => {
|
|
260
|
-
const asset = this.#assetsModule.getAsset(assetName);
|
|
261
|
-
let i = 0;
|
|
262
|
-
while (i < 3) {
|
|
263
|
-
try {
|
|
264
|
-
const { device } = await this.#getSelectedDevice();
|
|
265
|
-
await device.ensureApplicationIsOpened(asset.baseAsset.name);
|
|
266
|
-
}
|
|
267
|
-
catch (error) {
|
|
268
|
-
this.#logger.log(error);
|
|
269
|
-
}
|
|
270
|
-
finally {
|
|
271
|
-
await delay(1000);
|
|
272
|
-
i++;
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
};
|
|
276
268
|
getAddress = async ({ assetName, accountIndex, addressIndex, multisigData, displayOnDevice, }) => {
|
|
277
269
|
const asset = this.#assetsModule.getAsset(assetName);
|
|
278
270
|
const { device } = await this.#getSelectedDevice();
|
|
@@ -389,6 +381,7 @@ export class HardwareWallets {
|
|
|
389
381
|
const { device } = await this.#getSelectedDevice();
|
|
390
382
|
const source = device.descriptor.manufacturer;
|
|
391
383
|
const accountIndex = index ?? this.#walletAccounts.getNextIndex({ source });
|
|
384
|
+
const walletId = (await device.getWalletId?.()) ?? randomBytes(32).toString('hex');
|
|
392
385
|
const useableAssetNames = new Set(await device.listUseableAssetNames());
|
|
393
386
|
for (const assetName of useableAssetNames) {
|
|
394
387
|
const asset = this.#assetsModule.getAsset(assetName);
|
|
@@ -413,6 +406,7 @@ export class HardwareWallets {
|
|
|
413
406
|
model: device.descriptor.model,
|
|
414
407
|
assetNames: useableAssetNames,
|
|
415
408
|
keysToSync,
|
|
409
|
+
walletId,
|
|
416
410
|
});
|
|
417
411
|
return id;
|
|
418
412
|
};
|
|
@@ -430,18 +424,14 @@ export class HardwareWallets {
|
|
|
430
424
|
const { device } = await this.#getSelectedDevice();
|
|
431
425
|
const source = device.descriptor.manufacturer;
|
|
432
426
|
const label = source === WalletAccount.LEDGER_SRC ? 'Ledger' : 'Trezor';
|
|
433
|
-
const
|
|
434
|
-
? device.descriptor.internalDescriptor
|
|
435
|
-
:
|
|
436
|
-
randomBytes(32).toString('hex');
|
|
437
|
-
const { accountIndex, model } = this.#syncedKeysMap.get(syncedKeysId);
|
|
427
|
+
const { accountIndex, model, walletId } = this.#syncedKeysMap.get(syncedKeysId);
|
|
438
428
|
const walletAccount = new WalletAccount({
|
|
439
429
|
label: `${label}${accountIndex === 0 ? '' : '_' + accountIndex}`,
|
|
440
430
|
icon: source,
|
|
441
431
|
source,
|
|
442
432
|
model,
|
|
443
433
|
index: accountIndex,
|
|
444
|
-
id,
|
|
434
|
+
id: walletId,
|
|
445
435
|
isMultisig: !!isMultisig,
|
|
446
436
|
});
|
|
447
437
|
const walletAccountName = walletAccount.toString();
|
|
@@ -456,6 +446,11 @@ export class HardwareWallets {
|
|
|
456
446
|
submitPairingCode = async ({ code }) => {
|
|
457
447
|
return this.#trezorDiscovery.submitPairingCode(code);
|
|
458
448
|
};
|
|
449
|
+
setPassphraseMode = async ({ enabled }) => {
|
|
450
|
+
const { device } = await this.#getSelectedDevice();
|
|
451
|
+
const trezorDevice = this.#requireTrezorDevice(device);
|
|
452
|
+
trezorDevice.setPassphraseMode(enabled ? 'hidden' : 'standard');
|
|
453
|
+
};
|
|
459
454
|
requireDeviceFor = async ({ walletAccount }) => {
|
|
460
455
|
return {
|
|
461
456
|
signTransaction: this.signTransaction,
|
|
@@ -6,7 +6,6 @@ export interface HardwareSignerProvider {
|
|
|
6
6
|
scanForDevices: (deviceType: HardwareWalletManufacturer) => Promise<void>;
|
|
7
7
|
canAccessAsset: ({ assetName }: CanAccessAssetParams) => Promise<boolean>;
|
|
8
8
|
listUseableAssetNames: () => Promise<string[]>;
|
|
9
|
-
ensureApplicationIsOpened: ({ assetName }: EnsureApplicationIsOpenedParams) => Promise<void>;
|
|
10
9
|
scan: ({ assetName, accountIndexes, addressOffset }: ScanParams) => Promise<ScanResult>;
|
|
11
10
|
sync: ({ accountIndex }: SyncParams) => Promise<SyncedKeysId>;
|
|
12
11
|
addPublicKeysToWalletAccount: ({ walletAccount, syncedKeysId, }: StoreSyncedKeysParams) => Promise<void>;
|
|
@@ -14,6 +13,7 @@ export interface HardwareSignerProvider {
|
|
|
14
13
|
signTransaction: ({ baseAssetName, unsignedTx, walletAccount, }: SignTransactionParams) => Promise<any>;
|
|
15
14
|
signMessage: ({ assetName, derivationPath, message }: SignMessageParams) => Promise<any>;
|
|
16
15
|
submitPairingCode: ({ code }: ProcessPairingCodeParams) => Promise<any>;
|
|
16
|
+
setPassphraseMode: ({ enabled }: SetPassphraseModeParams) => Promise<void>;
|
|
17
17
|
}
|
|
18
18
|
type Asset = {
|
|
19
19
|
name: string;
|
|
@@ -64,6 +64,7 @@ export interface SyncedKeysData {
|
|
|
64
64
|
model: HardwareWalletDeviceModels;
|
|
65
65
|
assetNames: Set<string>;
|
|
66
66
|
keysToSync: KeyToSyncData[];
|
|
67
|
+
walletId: string;
|
|
67
68
|
}
|
|
68
69
|
export type KeyToSyncData = [KeyIdentifier, {
|
|
69
70
|
xpub?: string;
|
|
@@ -148,4 +149,7 @@ export interface RequireDeviceForParams {
|
|
|
148
149
|
export interface ProcessPairingCodeParams {
|
|
149
150
|
code: string;
|
|
150
151
|
}
|
|
152
|
+
export interface SetPassphraseModeParams {
|
|
153
|
+
enabled: boolean;
|
|
154
|
+
}
|
|
151
155
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/hardware-wallets",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.6.0",
|
|
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": {
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"@exodus/basic-utils": "^3.2.0",
|
|
33
33
|
"@exodus/bip32": "^4.0.2",
|
|
34
34
|
"@exodus/crypto": "^1.0.0-rc.14",
|
|
35
|
-
"@exodus/hw-common": "^3.
|
|
35
|
+
"@exodus/hw-common": "^3.4.0",
|
|
36
36
|
"@exodus/models": "^12.18.0",
|
|
37
37
|
"@exodus/redux-dependency-injection": "^4.0.0",
|
|
38
38
|
"@exodus/wild-emitter": "^1.1.0",
|
|
@@ -53,5 +53,5 @@
|
|
|
53
53
|
"access": "public",
|
|
54
54
|
"provenance": false
|
|
55
55
|
},
|
|
56
|
-
"gitHead": "
|
|
56
|
+
"gitHead": "43e7fa9467acd5e681d99473eb54d9e790130e04"
|
|
57
57
|
}
|