@exodus/hardware-wallets 3.4.1 → 3.5.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 +10 -0
- package/lib/module/hardware-wallets.js +53 -14
- package/lib/module/interfaces.d.ts +2 -0
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,16 @@
|
|
|
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.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
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
- feat: throw device unininitialized error for hw (#14601)
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
- fix: various trezor and hardware-wallets fixes (#14502)
|
|
15
|
+
|
|
6
16
|
## [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
17
|
|
|
8
18
|
### Bug Fixes
|
|
@@ -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 { NoDeviceFoundError, UserRefusedError } from '@exodus/hw-common';
|
|
6
|
+
import { DeviceUninitializedError, NoDeviceFoundError, UserRefusedError } from '@exodus/hw-common';
|
|
7
7
|
import restrictConcurrency from 'make-concurrent';
|
|
8
8
|
import pDefer from 'p-defer';
|
|
9
9
|
export class HardwareWallets {
|
|
@@ -31,12 +31,41 @@ export class HardwareWallets {
|
|
|
31
31
|
this.#walletAccountsAtom = walletAccountsAtom;
|
|
32
32
|
this.#walletAccounts = walletAccounts;
|
|
33
33
|
}
|
|
34
|
-
#
|
|
35
|
-
|
|
36
|
-
this.#trezorDiscovery.list()
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
#listTrezorDevicesOrEmpty = async () => {
|
|
35
|
+
try {
|
|
36
|
+
return await this.#trezorDiscovery.list();
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
if (error instanceof DeviceUninitializedError) {
|
|
40
|
+
throw error;
|
|
41
|
+
}
|
|
42
|
+
return [];
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
#listLedgerDevicesOrEmpty = async () => {
|
|
46
|
+
try {
|
|
47
|
+
return await this.#ledgerDiscovery.list();
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
#getSelectedDevice = async (walletAccount) => {
|
|
54
|
+
let descriptors;
|
|
55
|
+
const manufacturer = walletAccount?.source;
|
|
56
|
+
if (manufacturer === 'ledger') {
|
|
57
|
+
descriptors = await this.#listLedgerDevicesOrEmpty();
|
|
58
|
+
}
|
|
59
|
+
else if (manufacturer === 'trezor') {
|
|
60
|
+
descriptors = await this.#listTrezorDevicesOrEmpty();
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
const [trezors, ledgers] = await Promise.all([
|
|
64
|
+
this.#listTrezorDevicesOrEmpty(),
|
|
65
|
+
this.#listLedgerDevicesOrEmpty(),
|
|
66
|
+
]);
|
|
67
|
+
descriptors = [...trezors, ...ledgers];
|
|
68
|
+
}
|
|
40
69
|
if (descriptors[0]) {
|
|
41
70
|
return { device: await descriptors[0].get() };
|
|
42
71
|
}
|
|
@@ -70,7 +99,7 @@ export class HardwareWallets {
|
|
|
70
99
|
this.#isRetrying = true;
|
|
71
100
|
try {
|
|
72
101
|
this.#logger.debug(`Attempting to get selected device for signing request with id: ${id}`);
|
|
73
|
-
const { device } = await this.#getSelectedDevice();
|
|
102
|
+
const { device } = await this.#getSelectedDevice(request.walletAccount);
|
|
74
103
|
this.#logger.debug(`Attempting to sign for signing request with id: ${id}`);
|
|
75
104
|
const result = await request.sign({ device });
|
|
76
105
|
await this.#deleteSigningRequest(id);
|
|
@@ -115,7 +144,7 @@ export class HardwareWallets {
|
|
|
115
144
|
if (fromUI) {
|
|
116
145
|
this.#logger.debug(`Cancelling signing request on device for id: ${id}`);
|
|
117
146
|
try {
|
|
118
|
-
const { device } = await this.#getSelectedDevice();
|
|
147
|
+
const { device } = await this.#getSelectedDevice(request.walletAccount);
|
|
119
148
|
await device.cancelAction();
|
|
120
149
|
this.#logger.debug(`Succesfully cancelled signing request on device for id: ${id}`);
|
|
121
150
|
}
|
|
@@ -125,13 +154,14 @@ export class HardwareWallets {
|
|
|
125
154
|
}
|
|
126
155
|
request.reject(new UserRefusedError(!fromUI));
|
|
127
156
|
};
|
|
128
|
-
#signGeneric = restrictConcurrency(async ({ baseAssetName, scenario, sign }) => {
|
|
157
|
+
#signGeneric = restrictConcurrency(async ({ baseAssetName, scenario, sign, walletAccount }) => {
|
|
129
158
|
const id = randomBytes(16).toString('hex');
|
|
130
159
|
this.#logger.debug(`Starting signing request for ${baseAssetName} with scenario: ${scenario} and id: ${id}`);
|
|
131
160
|
const deferred = pDefer();
|
|
132
161
|
this.#signingRequest = {
|
|
133
162
|
id,
|
|
134
163
|
baseAssetName,
|
|
164
|
+
walletAccount,
|
|
135
165
|
sign: async ({ device }) => {
|
|
136
166
|
await this.#updateSigningRequest({
|
|
137
167
|
id,
|
|
@@ -158,7 +188,12 @@ export class HardwareWallets {
|
|
|
158
188
|
multisigData,
|
|
159
189
|
});
|
|
160
190
|
};
|
|
161
|
-
return this.#signGeneric({
|
|
191
|
+
return this.#signGeneric({
|
|
192
|
+
baseAssetName,
|
|
193
|
+
scenario: 'signTransaction',
|
|
194
|
+
sign,
|
|
195
|
+
walletAccount,
|
|
196
|
+
});
|
|
162
197
|
};
|
|
163
198
|
signMessage = async ({ assetName, derivationPath, message }) => {
|
|
164
199
|
const baseAssetName = this.#assetsModule.getAsset(assetName).baseAsset.name;
|
|
@@ -178,7 +213,11 @@ export class HardwareWallets {
|
|
|
178
213
|
return true;
|
|
179
214
|
}
|
|
180
215
|
}
|
|
181
|
-
catch {
|
|
216
|
+
catch (error) {
|
|
217
|
+
if (error instanceof DeviceUninitializedError) {
|
|
218
|
+
throw error;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
182
221
|
try {
|
|
183
222
|
const devices = await this.#ledgerDiscovery.list();
|
|
184
223
|
return devices.length > 0;
|
|
@@ -199,8 +238,8 @@ export class HardwareWallets {
|
|
|
199
238
|
};
|
|
200
239
|
getAvailableDevices = async () => {
|
|
201
240
|
const [ledgers, trezors] = await Promise.all([
|
|
202
|
-
this.#
|
|
203
|
-
this.#
|
|
241
|
+
this.#listLedgerDevicesOrEmpty(),
|
|
242
|
+
this.#listTrezorDevicesOrEmpty(),
|
|
204
243
|
]);
|
|
205
244
|
return [...ledgers, ...trezors].map((device) => ({
|
|
206
245
|
model: device.model,
|
|
@@ -84,6 +84,7 @@ export interface GenericSignParams {
|
|
|
84
84
|
baseAssetName: string;
|
|
85
85
|
scenario: 'signTransaction' | 'signMessage';
|
|
86
86
|
sign: GenericSignCallback;
|
|
87
|
+
walletAccount?: WalletAccount;
|
|
87
88
|
}
|
|
88
89
|
export interface SigningRequestState {
|
|
89
90
|
id: string;
|
|
@@ -94,6 +95,7 @@ export interface SigningRequestState {
|
|
|
94
95
|
export interface SigningRequest {
|
|
95
96
|
id: string;
|
|
96
97
|
baseAssetName?: string;
|
|
98
|
+
walletAccount?: WalletAccount;
|
|
97
99
|
sign: GenericSignCallback;
|
|
98
100
|
resolve: (result: any) => void;
|
|
99
101
|
reject: (error: Error) => void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/hardware-wallets",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.5.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.3.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": "91c5651b997e904755c35158697523f816611d71"
|
|
57
57
|
}
|