@exodus/hardware-wallets 1.4.0 → 1.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 +11 -0
- package/lib/api/index.d.ts +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/module/hardware-wallets.d.ts +1 -1
- package/lib/module/hardware-wallets.js +28 -16
- package/lib/module/interfaces.d.ts +4 -3
- package/package.json +4 -4
- package/lib/module/errors.d.ts +0 -4
- package/lib/module/errors.js +0 -6
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,17 @@
|
|
|
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
|
+
## [1.5.0](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/hardware-wallets@1.4.0...@exodus/hardware-wallets@1.5.0) (2024-10-17)
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
- add `getSelectedDevice` ([#9822](https://github.com/ExodusMovement/exodus-hydra/issues/9822)) ([2c18c22](https://github.com/ExodusMovement/exodus-hydra/commit/2c18c22d419ba9136cd8b264e946b151df438c59))
|
|
11
|
+
- support adding model to wallet account ([#9936](https://github.com/ExodusMovement/exodus-hydra/issues/9936)) ([8c858f6](https://github.com/ExodusMovement/exodus-hydra/commit/8c858f6e08e41bee3261f444c3d25e8bdd385014))
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
- unify user refused error handling ([#10052](https://github.com/ExodusMovement/exodus-hydra/issues/10052)) ([db85d10](https://github.com/ExodusMovement/exodus-hydra/commit/db85d108333630d09bad545c5ec1169b937e08fe))
|
|
16
|
+
|
|
6
17
|
## [1.4.0](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/hardware-wallets@1.3.0...@exodus/hardware-wallets@1.4.0) (2024-10-07)
|
|
7
18
|
|
|
8
19
|
### Features
|
package/lib/api/index.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ declare const hardwareWalletsApiDefinition: {
|
|
|
10
10
|
hardwareWallets: {
|
|
11
11
|
isDeviceConnected: () => Promise<boolean>;
|
|
12
12
|
getAvailableDevices: () => Promise<{
|
|
13
|
-
model: ("
|
|
13
|
+
model: import("libraries/hw-common/lib/types.js").HardwareWalletDeviceModels;
|
|
14
14
|
name: string;
|
|
15
15
|
}[]>;
|
|
16
16
|
listUseableAssetNames: () => Promise<string[]>;
|
package/lib/index.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ declare const hardwareWallets: () => {
|
|
|
13
13
|
hardwareWallets: {
|
|
14
14
|
isDeviceConnected: () => Promise<boolean>;
|
|
15
15
|
getAvailableDevices: () => Promise<{
|
|
16
|
-
model: ("
|
|
16
|
+
model: import("libraries/hw-common/lib/types.js").HardwareWalletDeviceModels;
|
|
17
17
|
name: string;
|
|
18
18
|
}[]>;
|
|
19
19
|
listUseableAssetNames: () => Promise<string[]>;
|
|
@@ -26,7 +26,7 @@ export declare class HardwareWallets implements HardwareSignerProvider {
|
|
|
26
26
|
isDeviceConnected: () => Promise<boolean>;
|
|
27
27
|
scanForDevices: () => Promise<void>;
|
|
28
28
|
getAvailableDevices: () => Promise<{
|
|
29
|
-
model: ("
|
|
29
|
+
model: import("@exodus/hw-common").HardwareWalletDeviceModels;
|
|
30
30
|
name: string;
|
|
31
31
|
}[]>;
|
|
32
32
|
canAccessAsset: ({ assetName }: CanAccessAssetParams) => Promise<boolean>;
|
|
@@ -3,7 +3,7 @@ import { WalletAccount } from '@exodus/models';
|
|
|
3
3
|
import Emitter from '@exodus/wild-emitter';
|
|
4
4
|
import randomBytes from 'randombytes';
|
|
5
5
|
import delay from 'delay';
|
|
6
|
-
import {
|
|
6
|
+
import { NoDeviceFoundError, UserRefusedError } from '@exodus/hw-common';
|
|
7
7
|
export class HardwareWallets {
|
|
8
8
|
#assetsModule;
|
|
9
9
|
#ledgerDiscovery;
|
|
@@ -25,6 +25,13 @@ export class HardwareWallets {
|
|
|
25
25
|
this.#walletAccountsAtom = walletAccountsAtom;
|
|
26
26
|
this.#walletAccounts = walletAccounts;
|
|
27
27
|
}
|
|
28
|
+
#getSelectedDevice = async () => {
|
|
29
|
+
const descriptors = await this.#ledgerDiscovery.list();
|
|
30
|
+
if (descriptors[0]) {
|
|
31
|
+
return { device: await descriptors[0].get() };
|
|
32
|
+
}
|
|
33
|
+
throw new NoDeviceFoundError();
|
|
34
|
+
};
|
|
28
35
|
#requestUserAction = async (params) => {
|
|
29
36
|
const rpc = this.#userInterface.getRPC();
|
|
30
37
|
return rpc.callMethod('handle-hardware-wallet', params);
|
|
@@ -42,9 +49,9 @@ export class HardwareWallets {
|
|
|
42
49
|
});
|
|
43
50
|
needUserApproval = false;
|
|
44
51
|
}
|
|
45
|
-
const
|
|
46
|
-
await
|
|
47
|
-
const result = await sign({
|
|
52
|
+
const { device } = await this.#getSelectedDevice();
|
|
53
|
+
await device.ensureApplicationIsOpened(baseAssetName);
|
|
54
|
+
const result = await sign({ device });
|
|
48
55
|
this.#requestUserAction({ scenario: 'completed' });
|
|
49
56
|
return result;
|
|
50
57
|
}
|
|
@@ -52,6 +59,9 @@ export class HardwareWallets {
|
|
|
52
59
|
if (error.message.includes('timeout')) {
|
|
53
60
|
break;
|
|
54
61
|
}
|
|
62
|
+
else if (error.name === 'UserRefusedError') {
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
55
65
|
if (error.name === 'DisconnectedDeviceDuringOperation') {
|
|
56
66
|
this.#requestUserAction({
|
|
57
67
|
scenario,
|
|
@@ -80,15 +90,15 @@ export class HardwareWallets {
|
|
|
80
90
|
}
|
|
81
91
|
}
|
|
82
92
|
this.#requestUserAction({ scenario: 'completed' });
|
|
83
|
-
throw new
|
|
93
|
+
throw new UserRefusedError(false);
|
|
84
94
|
};
|
|
85
95
|
signTransaction = async ({ baseAssetName, unsignedTx, walletAccount, multisigData, }) => {
|
|
86
96
|
const baseAsset = this.#assetsModule.getAsset(baseAssetName);
|
|
87
97
|
const accountIndex = walletAccount.index;
|
|
88
|
-
const sign = async ({
|
|
98
|
+
const sign = async ({ device }) => {
|
|
89
99
|
return baseAsset.api.signHardware({
|
|
90
100
|
unsignedTx,
|
|
91
|
-
hardwareDevice,
|
|
101
|
+
hardwareDevice: device,
|
|
92
102
|
accountIndex,
|
|
93
103
|
multisigData,
|
|
94
104
|
});
|
|
@@ -97,8 +107,8 @@ export class HardwareWallets {
|
|
|
97
107
|
};
|
|
98
108
|
signMessage = async ({ assetName, derivationPath, message }) => {
|
|
99
109
|
const baseAssetName = this.#assetsModule.getAsset(assetName).baseAsset.name;
|
|
100
|
-
const sign = async ({
|
|
101
|
-
return
|
|
110
|
+
const sign = async ({ device }) => {
|
|
111
|
+
return device.signMessage({
|
|
102
112
|
assetName: baseAssetName,
|
|
103
113
|
derivationPath,
|
|
104
114
|
message,
|
|
@@ -128,12 +138,12 @@ export class HardwareWallets {
|
|
|
128
138
|
};
|
|
129
139
|
canAccessAsset = async ({ assetName }) => {
|
|
130
140
|
const asset = this.#assetsModule.getAsset(assetName);
|
|
131
|
-
const device = await this.#
|
|
141
|
+
const { device } = await this.#getSelectedDevice();
|
|
132
142
|
const useableAssetNames = new Set(await device.listUseableAssetNames());
|
|
133
143
|
return useableAssetNames.has(asset.baseAsset.name);
|
|
134
144
|
};
|
|
135
145
|
listUseableAssetNames = async () => {
|
|
136
|
-
const device = await this.#
|
|
146
|
+
const { device } = await this.#getSelectedDevice();
|
|
137
147
|
return device.listUseableAssetNames();
|
|
138
148
|
};
|
|
139
149
|
ensureApplicationIsOpened = async ({ assetName }) => {
|
|
@@ -141,8 +151,8 @@ export class HardwareWallets {
|
|
|
141
151
|
let i = 0;
|
|
142
152
|
while (i < 3) {
|
|
143
153
|
try {
|
|
144
|
-
const
|
|
145
|
-
await
|
|
154
|
+
const { device } = await this.#getSelectedDevice();
|
|
155
|
+
await device.ensureApplicationIsOpened(asset.baseAsset.name);
|
|
146
156
|
}
|
|
147
157
|
catch (error) {
|
|
148
158
|
this.#logger.log(error);
|
|
@@ -166,7 +176,7 @@ export class HardwareWallets {
|
|
|
166
176
|
chainIndex: 0,
|
|
167
177
|
addressIndex,
|
|
168
178
|
});
|
|
169
|
-
const device = await this.#
|
|
179
|
+
const { device } = await this.#getSelectedDevice();
|
|
170
180
|
return device.getAddress({
|
|
171
181
|
assetName,
|
|
172
182
|
derivationPath,
|
|
@@ -259,7 +269,7 @@ export class HardwareWallets {
|
|
|
259
269
|
};
|
|
260
270
|
sync = async ({ accountIndex: index, isMultisig } = {}) => {
|
|
261
271
|
const keysToSync = [];
|
|
262
|
-
const device = await this.#
|
|
272
|
+
const { device } = await this.#getSelectedDevice();
|
|
263
273
|
const accountIndex = index ?? this.#walletAccounts.getNextIndex({ source: WalletAccount.LEDGER_SRC });
|
|
264
274
|
const useableAssetNames = new Set(await device.listUseableAssetNames());
|
|
265
275
|
for (const assetName of useableAssetNames) {
|
|
@@ -279,6 +289,7 @@ export class HardwareWallets {
|
|
|
279
289
|
const id = randomBytes(16).toString('hex');
|
|
280
290
|
this.#syncedKeysMap.set(id, {
|
|
281
291
|
accountIndex,
|
|
292
|
+
model: device.descriptor.model,
|
|
282
293
|
assetNames: useableAssetNames,
|
|
283
294
|
keysToSync,
|
|
284
295
|
});
|
|
@@ -295,11 +306,12 @@ export class HardwareWallets {
|
|
|
295
306
|
};
|
|
296
307
|
create = async ({ syncedKeysId, isMultisig }) => {
|
|
297
308
|
assert(this.#syncedKeysMap.has(syncedKeysId), `no synchronized keys found for id ${syncedKeysId}`);
|
|
298
|
-
const { accountIndex } = this.#syncedKeysMap.get(syncedKeysId);
|
|
309
|
+
const { accountIndex, model } = this.#syncedKeysMap.get(syncedKeysId);
|
|
299
310
|
const walletAccount = new WalletAccount({
|
|
300
311
|
label: `Ledger${accountIndex === 0 ? '' : ' ' + accountIndex}`,
|
|
301
312
|
icon: 'ledger',
|
|
302
313
|
source: WalletAccount.LEDGER_SRC,
|
|
314
|
+
model,
|
|
303
315
|
index: accountIndex,
|
|
304
316
|
id: randomBytes(32).toString('hex'),
|
|
305
317
|
isMultisig: !!isMultisig,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { WalletAccount } from '@exodus/models';
|
|
2
|
-
import type { HardwareWalletDevice, MultisigData, SignMessageParams } from '@exodus/hw-common';
|
|
2
|
+
import type { HardwareWalletDeviceModels, HardwareWalletDevice, MultisigData, SignMessageParams } from '@exodus/hw-common';
|
|
3
3
|
import type KeyIdentifier from '@exodus/key-identifier';
|
|
4
4
|
export interface HardwareSignerProvider {
|
|
5
5
|
isDeviceConnected: () => Promise<boolean>;
|
|
@@ -59,6 +59,7 @@ export interface SyncParams {
|
|
|
59
59
|
export type SyncedKeysId = string;
|
|
60
60
|
export interface SyncedKeysData {
|
|
61
61
|
accountIndex: number;
|
|
62
|
+
model: HardwareWalletDeviceModels;
|
|
62
63
|
assetNames: Set<string>;
|
|
63
64
|
keysToSync: KeyToSyncData[];
|
|
64
65
|
}
|
|
@@ -74,8 +75,8 @@ export interface CreateParams {
|
|
|
74
75
|
syncedKeysId: SyncedKeysId;
|
|
75
76
|
isMultisig?: boolean;
|
|
76
77
|
}
|
|
77
|
-
export type GenericSignCallback = ({
|
|
78
|
-
|
|
78
|
+
export type GenericSignCallback = ({ device }: {
|
|
79
|
+
device: HardwareWalletDevice;
|
|
79
80
|
}) => Promise<any>;
|
|
80
81
|
export interface GenericSignParams {
|
|
81
82
|
baseAssetName: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/hardware-wallets",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.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": {
|
|
@@ -24,10 +24,11 @@
|
|
|
24
24
|
"clean": "run -T tsc --build --clean",
|
|
25
25
|
"lint": "run -T eslint .",
|
|
26
26
|
"lint:fix": "yarn lint --fix",
|
|
27
|
-
"test": "run -T jest",
|
|
27
|
+
"test": "run -T exodus-test --jest --esbuild",
|
|
28
28
|
"prepublishOnly": "yarn run -T build --scope @exodus/hardware-wallets"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
+
"@exodus/hw-common": "^3.0.0",
|
|
31
32
|
"@exodus/models": "^12.0.1",
|
|
32
33
|
"@exodus/wild-emitter": "^1.1.0",
|
|
33
34
|
"delay": "^5.0.0",
|
|
@@ -37,11 +38,10 @@
|
|
|
37
38
|
"devDependencies": {
|
|
38
39
|
"@exodus/atoms": "^9.0.0",
|
|
39
40
|
"@exodus/dependency-types": "^2.1.0",
|
|
40
|
-
"@exodus/hw-common": "^2.5.0",
|
|
41
41
|
"@exodus/key-identifier": "^1.3.0",
|
|
42
42
|
"@exodus/logger": "^1.2.2",
|
|
43
43
|
"@exodus/public-key-provider": "^3.0.0",
|
|
44
44
|
"@types/randombytes": "^2.0.3"
|
|
45
45
|
},
|
|
46
|
-
"gitHead": "
|
|
46
|
+
"gitHead": "a4f949331317cbeb49ea2392703722914a67fcac"
|
|
47
47
|
}
|
package/lib/module/errors.d.ts
DELETED