@exodus/hardware-wallets 2.0.5 → 3.0.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 CHANGED
@@ -3,6 +3,22 @@
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.0.0](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/hardware-wallets@2.1.0...@exodus/hardware-wallets@3.0.0) (2025-06-16)
7
+
8
+ ### ⚠ BREAKING CHANGES
9
+
10
+ - rework hardware wallet UI signing (#12852)
11
+
12
+ ### Features
13
+
14
+ - feat!: rework hardware wallet UI signing (#12852)
15
+
16
+ ## [2.1.0](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/hardware-wallets@2.0.5...@exodus/hardware-wallets@2.1.0) (2025-05-13)
17
+
18
+ ### Features
19
+
20
+ - feat(wallet-accounts): default ledger color and icon (#12426)
21
+
6
22
  ## [2.0.5](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/hardware-wallets@2.0.4...@exodus/hardware-wallets@2.0.5) (2025-05-09)
7
23
 
8
24
  ### Bug Fixes
@@ -21,6 +21,8 @@ declare const hardwareWalletsApiDefinition: {
21
21
  sync: ({ accountIndex: index, isMultisig }?: import("../module/interfaces.js").SyncParams) => Promise<import("../module/interfaces.js").SyncedKeysId>;
22
22
  addPublicKeysToWalletAccount: ({ walletAccount, syncedKeysId }: import("../module/interfaces.js").StoreSyncedKeysParams) => Promise<void>;
23
23
  create: ({ syncedKeysId, isMultisig }: import("../module/interfaces.js").CreateParams) => Promise<import("libraries/models/lib/index.js").WalletAccount>;
24
+ retrySigningRequest: (id: string) => Promise<void>;
25
+ cancelSigningRequest: (id: string, fromUI: boolean) => Promise<void>;
24
26
  };
25
27
  };
26
28
  readonly dependencies: readonly ["hardwareWallets", "txLogMonitors", "restoreProgressTracker"];
package/lib/api/index.js CHANGED
@@ -28,6 +28,8 @@ const createHardwareWalletsApi = ({ hardwareWallets, restoreProgressTracker, txL
28
28
  sync: hardwareWallets.sync,
29
29
  addPublicKeysToWalletAccount: hardwareWallets.addPublicKeysToWalletAccount,
30
30
  create: hardwareWallets.create,
31
+ retrySigningRequest: hardwareWallets.retrySigningRequest,
32
+ cancelSigningRequest: hardwareWallets.cancelSigningRequest,
31
33
  },
32
34
  };
33
35
  };
@@ -0,0 +1,8 @@
1
+ import type { SigningRequestState } from '../module/interfaces.js';
2
+ export declare const hardwareWalletSigningRequestsAtomDefinition: {
3
+ readonly id: "hardwareWalletSigningRequestsAtom";
4
+ readonly type: "atom";
5
+ readonly factory: () => import("@exodus/atoms").Atom<SigningRequestState>;
6
+ readonly dependencies: readonly [];
7
+ readonly public: false;
8
+ };
@@ -0,0 +1,10 @@
1
+ import { createInMemoryAtom } from '@exodus/atoms';
2
+ export const hardwareWalletSigningRequestsAtomDefinition = {
3
+ id: 'hardwareWalletSigningRequestsAtom',
4
+ type: 'atom',
5
+ factory: () => createInMemoryAtom({
6
+ defaultValue: Object.create(null),
7
+ }),
8
+ dependencies: [],
9
+ public: false,
10
+ };
@@ -1,3 +1,4 @@
1
+ export { hardwareWalletSigningRequestsAtomDefinition } from './hardwareWalletSigningRequestsAtom.js';
1
2
  type WalletAccountName = string;
2
3
  type AssetName = string;
3
4
  export type WalletAccountNameToConnectedAssetNamesMap = Record<WalletAccountName, AssetName[]>;
@@ -8,4 +9,3 @@ export declare const hardwareWalletConnectedAssetNamesAtomDefinition: {
8
9
  readonly factory: ({ assetsModule, hardwareWalletPublicKeysAtom, walletAccountsAtom, }: any) => import("@exodus/atoms").ReadonlyAtom<unknown>;
9
10
  readonly dependencies: readonly ["hardwareWalletPublicKeysAtom", "assetsModule", "walletAccountsAtom"];
10
11
  };
11
- export {};
@@ -1,6 +1,7 @@
1
1
  import { combine, compute } from '@exodus/atoms';
2
2
  import { memoize } from '@exodus/basic-utils';
3
3
  import { HARDENED_OFFSET } from '@exodus/bip32';
4
+ export { hardwareWalletSigningRequestsAtomDefinition } from './hardwareWalletSigningRequestsAtom.js';
4
5
  export const createHardwareWalletConnectedAssetNamesAtom = ({ assetsModule, hardwareWalletPublicKeysAtom, walletAccountsAtom, }) => {
5
6
  const selector = memoize(({ hardwareWalletPublicKeys, walletAccounts }) => {
6
7
  const result = Object.create(null);
package/lib/index.d.ts CHANGED
@@ -24,6 +24,8 @@ declare const hardwareWallets: () => {
24
24
  sync: ({ accountIndex: index, isMultisig }?: import("./module/interfaces.js").SyncParams) => Promise<import("./module/interfaces.js").SyncedKeysId>;
25
25
  addPublicKeysToWalletAccount: ({ walletAccount, syncedKeysId }: import("./module/interfaces.js").StoreSyncedKeysParams) => Promise<void>;
26
26
  create: ({ syncedKeysId, isMultisig }: import("./module/interfaces.js").CreateParams) => Promise<import("libraries/models/lib/index.js").WalletAccount>;
27
+ retrySigningRequest: (id: string) => Promise<void>;
28
+ cancelSigningRequest: (id: string, fromUI: boolean) => Promise<void>;
27
29
  };
28
30
  };
29
31
  readonly dependencies: readonly ["hardwareWallets", "txLogMonitors", "restoreProgressTracker"];
@@ -33,7 +35,7 @@ declare const hardwareWallets: () => {
33
35
  readonly id: "hardwareWallets";
34
36
  readonly type: "module";
35
37
  readonly factory: (opts: import("./module/hardware-wallets.js").Dependencies) => import("./module/hardware-wallets.js").HardwareWallets;
36
- readonly dependencies: readonly ["assetsModule", "logger", "ledgerDiscovery", "userInterface", "publicKeyStore", "wallet", "walletAccountsAtom", "walletAccounts"];
38
+ readonly dependencies: readonly ["assetsModule", "logger", "ledgerDiscovery", "publicKeyStore", "hardwareWalletSigningRequestsAtom", "wallet", "walletAccountsAtom", "walletAccounts"];
37
39
  readonly public: true;
38
40
  };
39
41
  }, {
@@ -43,19 +45,28 @@ declare const hardwareWallets: () => {
43
45
  readonly factory: ({ assetsModule, hardwareWalletPublicKeysAtom, walletAccountsAtom, }: any) => import("libraries/atoms/lib/index.js").ReadonlyAtom<unknown>;
44
46
  readonly dependencies: readonly ["hardwareWalletPublicKeysAtom", "assetsModule", "walletAccountsAtom"];
45
47
  };
48
+ }, {
49
+ readonly definition: {
50
+ readonly id: "hardwareWalletSigningRequestsAtom";
51
+ readonly type: "atom";
52
+ readonly factory: () => import("libraries/atoms/lib/index.js").Atom<import("./module/interfaces.js").SigningRequestState>;
53
+ readonly dependencies: readonly [];
54
+ readonly public: false;
55
+ };
46
56
  }, {
47
57
  readonly definition: {
48
58
  readonly id: "hardwareWalletsPlugin";
49
59
  readonly type: "plugin";
50
- readonly factory: ({ hardwareWalletConnectedAssetNamesAtom, port, }: {
60
+ readonly factory: ({ hardwareWalletConnectedAssetNamesAtom, hardwareWalletSigningRequestsAtom, port, }: {
51
61
  hardwareWalletConnectedAssetNamesAtom: import("libraries/atoms/lib/index.js").Atom<import("./atoms/index.js").WalletAccountNameToConnectedAssetNamesMap>;
62
+ hardwareWalletSigningRequestsAtom: import("libraries/atoms/lib/index.js").Atom<import("./module/interfaces.js").SigningRequestState>;
52
63
  port: import("./shared/types.js").Port;
53
64
  }) => {
54
65
  onUnlock: () => void;
55
66
  onLoad: () => void;
56
67
  onStop: () => void;
57
68
  };
58
- readonly dependencies: readonly ["hardwareWalletConnectedAssetNamesAtom", "port"];
69
+ readonly dependencies: readonly ["hardwareWalletConnectedAssetNamesAtom", "hardwareWalletSigningRequestsAtom", "port"];
59
70
  };
60
71
  }];
61
72
  };
package/lib/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import hardwareWalletsApiDefinition from './api/index.js';
2
2
  import hardwareWalletsModuleDefinition from './module/hardware-wallets.js';
3
- import { hardwareWalletConnectedAssetNamesAtomDefinition } from './atoms/index.js';
3
+ import { hardwareWalletConnectedAssetNamesAtomDefinition, hardwareWalletSigningRequestsAtomDefinition, } from './atoms/index.js';
4
4
  import hardwareWalletsPluginDefinition from './plugin/index.js';
5
5
  const hardwareWallets = () => {
6
6
  return {
@@ -15,6 +15,9 @@ const hardwareWallets = () => {
15
15
  {
16
16
  definition: hardwareWalletConnectedAssetNamesAtomDefinition,
17
17
  },
18
+ {
19
+ definition: hardwareWalletSigningRequestsAtomDefinition,
20
+ },
18
21
  {
19
22
  definition: hardwareWalletsPluginDefinition,
20
23
  },
@@ -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, EnsureApplicationIsOpenedParams, SignTransactionParams, ScanResult, SyncedKeysId, GetAddressParams, RequireDeviceForParams } from './interfaces.js';
3
+ import type { HardwareSignerProvider, CanAccessAssetParams, CreateParams, StoreSyncedKeysParams, ScanParams, SyncParams, EnsureApplicationIsOpenedParams, SignTransactionParams, ScanResult, SyncedKeysId, GetAddressParams, RequireDeviceForParams, SigningRequestState } from './interfaces.js';
4
4
  import type { HardwareWalletDiscovery, 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';
@@ -9,7 +9,7 @@ export type Dependencies = {
9
9
  assetsModule: any;
10
10
  ledgerDiscovery: HardwareWalletDiscovery;
11
11
  logger: Logger;
12
- userInterface: any;
12
+ hardwareWalletSigningRequestsAtom: Atom<SigningRequestState>;
13
13
  publicKeyStore: IPublicKeyStore;
14
14
  wallet: any;
15
15
  walletAccountsAtom: Atom<WalletAccount>;
@@ -20,7 +20,9 @@ export type Dependencies = {
20
20
  export declare class HardwareWallets implements HardwareSignerProvider {
21
21
  #private;
22
22
  readonly events: Emitter<string, any>;
23
- constructor({ assetsModule, ledgerDiscovery, logger, userInterface, publicKeyStore, wallet, walletAccountsAtom, walletAccounts, }: Dependencies);
23
+ constructor({ assetsModule, ledgerDiscovery, logger, hardwareWalletSigningRequestsAtom, publicKeyStore, wallet, walletAccountsAtom, walletAccounts, }: Dependencies);
24
+ retrySigningRequest: (id: string) => Promise<void>;
25
+ cancelSigningRequest: (id: string, fromUI: boolean) => Promise<void>;
24
26
  signTransaction: ({ baseAssetName, unsignedTx, walletAccount, multisigData, }: SignTransactionParams) => Promise<any>;
25
27
  signMessage: ({ assetName, derivationPath, message }: SignMessageParams) => Promise<any>;
26
28
  isDeviceConnected: () => Promise<boolean>;
@@ -46,7 +48,7 @@ declare const hardwareWalletsModuleDefinition: {
46
48
  readonly id: "hardwareWallets";
47
49
  readonly type: "module";
48
50
  readonly factory: (opts: Dependencies) => HardwareWallets;
49
- readonly dependencies: readonly ["assetsModule", "logger", "ledgerDiscovery", "userInterface", "publicKeyStore", "wallet", "walletAccountsAtom", "walletAccounts"];
51
+ readonly dependencies: readonly ["assetsModule", "logger", "ledgerDiscovery", "publicKeyStore", "hardwareWalletSigningRequestsAtom", "wallet", "walletAccountsAtom", "walletAccounts"];
50
52
  readonly public: true;
51
53
  };
52
54
  export default hardwareWalletsModuleDefinition;
@@ -4,23 +4,26 @@ import Emitter from '@exodus/wild-emitter';
4
4
  import { randomBytes } from '@exodus/crypto/randomBytes';
5
5
  import delay from 'delay';
6
6
  import { NoDeviceFoundError, UserRefusedError } from '@exodus/hw-common';
7
+ import restrictConcurrency from 'make-concurrent';
8
+ import pDefer from 'p-defer';
7
9
  export class HardwareWallets {
8
10
  #assetsModule;
9
11
  #ledgerDiscovery;
10
12
  #logger;
11
- #userInterface;
12
13
  #publicKeyStore;
14
+ #signingRequestAtom;
13
15
  #wallet;
14
16
  #walletAccountsAtom;
15
17
  #walletAccounts;
16
18
  #syncedKeysMap = new Map();
19
+ #signingRequest;
17
20
  events = new Emitter();
18
- constructor({ assetsModule, ledgerDiscovery, logger, userInterface, publicKeyStore, wallet, walletAccountsAtom, walletAccounts, }) {
21
+ constructor({ assetsModule, ledgerDiscovery, logger, hardwareWalletSigningRequestsAtom, publicKeyStore, wallet, walletAccountsAtom, walletAccounts, }) {
19
22
  this.#assetsModule = assetsModule;
20
23
  this.#ledgerDiscovery = ledgerDiscovery;
21
24
  this.#logger = logger;
22
- this.#userInterface = userInterface;
23
25
  this.#publicKeyStore = publicKeyStore;
26
+ this.#signingRequestAtom = hardwareWalletSigningRequestsAtom;
24
27
  this.#wallet = wallet;
25
28
  this.#walletAccountsAtom = walletAccountsAtom;
26
29
  this.#walletAccounts = walletAccounts;
@@ -32,66 +35,100 @@ export class HardwareWallets {
32
35
  }
33
36
  throw new NoDeviceFoundError();
34
37
  };
35
- #requestUserAction = async (params) => {
36
- const rpc = this.#userInterface.getRPC();
37
- return rpc.callMethod('handle-hardware-wallet', params);
38
+ #updateSigningRequest = async (state) => {
39
+ this.#logger.debug(`Updating signing request state: ${JSON.stringify(state)}`);
40
+ await this.#signingRequestAtom.set(state);
41
+ this.#logger.debug(`Finished updating signing request state: ${JSON.stringify(state)}`);
38
42
  };
39
- #signGeneric = async ({ baseAssetName, scenario, sign }) => {
40
- let attempts = 0;
41
- const MAX_ATTEMPTS = 50;
42
- while (attempts < MAX_ATTEMPTS) {
43
+ #deleteSigningRequest = async (id) => {
44
+ if (this.#signingRequest?.id === id) {
45
+ this.#signingRequest = undefined;
46
+ await this.#signingRequestAtom.reset();
47
+ this.#logger.debug(`Signing request with id: ${id} has been deleted`);
48
+ }
49
+ else {
50
+ this.#logger.warn(`No signing request found for id: ${id}`);
51
+ }
52
+ };
53
+ retrySigningRequest = async (id) => {
54
+ const request = this.#signingRequest;
55
+ if (request?.id !== id) {
56
+ this.#logger.warn(`No signing request found for id: ${id}`);
57
+ return;
58
+ }
59
+ try {
60
+ this.#logger.debug(`Attempting to get selected device for signing request with id: ${id}`);
61
+ const { device } = await this.#getSelectedDevice();
62
+ this.#logger.debug(`Attempting to sign for signing request with id: ${id}`);
63
+ const result = await request.sign({ device });
64
+ await this.#deleteSigningRequest(id);
65
+ request.resolve(result);
66
+ }
67
+ catch (error) {
68
+ const _error = error;
69
+ if (['DisconnectedDevice', 'DisconnectedDeviceDuringOperation'].includes(error.name)) {
70
+ this.#logger.debug(`Device disconnected during signing request, likely due to app opening: ${id}`, _error);
71
+ await delay(300);
72
+ if (this.#signingRequest?.id !== id) {
73
+ this.#logger.warn(`Signing request with id: ${id} was cancelled, not retrying`);
74
+ return;
75
+ }
76
+ await this.retrySigningRequest(id);
77
+ return;
78
+ }
79
+ if (_error.message.includes('timeout') || _error.name === 'UserRefusedError') {
80
+ await this.cancelSigningRequest(id, false);
81
+ return;
82
+ }
83
+ await this.#updateSigningRequest({
84
+ id,
85
+ scenario: 'error',
86
+ error: _error,
87
+ });
88
+ }
89
+ };
90
+ cancelSigningRequest = async (id, fromUI) => {
91
+ const request = this.#signingRequest;
92
+ this.#logger.debug(`Cancelling signing request for id: ${id}, fromUI: ${fromUI}`);
93
+ if (request?.id !== id) {
94
+ this.#logger.warn(`No signing request found for id: ${id}`);
95
+ return;
96
+ }
97
+ await this.#deleteSigningRequest(id);
98
+ if (fromUI) {
99
+ this.#logger.debug(`Cancelling signing request on device for id: ${id}`);
43
100
  try {
44
- const approvePromise = this.#requestUserAction({
45
- scenario,
46
- baseAssetName,
47
- });
48
101
  const { device } = await this.#getSelectedDevice();
49
- const runSign = async () => {
50
- await device.ensureApplicationIsOpened(baseAssetName);
51
- return sign({ device });
52
- };
53
- const result = await Promise.race([approvePromise, runSign()]);
54
- if (typeof result === 'object' && result.tryAgain === false) {
55
- void device.cancelAction();
56
- throw new UserRefusedError(false);
57
- }
58
- void this.#requestUserAction({ scenario: 'completed' });
59
- return result;
102
+ await device.cancelAction();
103
+ this.#logger.debug(`Succesfully cancelled signing request on device for id: ${id}`);
60
104
  }
61
105
  catch (error) {
62
- if (error.message.includes('timeout')) {
63
- break;
64
- }
65
- else if (error.name === 'UserRefusedError') {
66
- void this.#requestUserAction({ scenario: 'completed' });
67
- throw error;
68
- }
69
- if (['DisconnectedDevice', 'DisconnectedDeviceDuringOperation'].includes(error.name)) {
70
- continue;
71
- }
72
- try {
73
- const { tryAgain } = await this.#requestUserAction({
74
- error,
75
- baseAssetName,
76
- });
77
- if (!tryAgain) {
78
- this.#logger.warn(error);
79
- break;
80
- }
81
- }
82
- catch (_error) {
83
- this.#logger.error(_error);
84
- break;
85
- }
86
- }
87
- finally {
88
- attempts++;
89
- await delay(200);
106
+ this.#logger.error(`Failed to cancel signing request on device for id: ${id}`, error);
90
107
  }
91
108
  }
92
- void this.#requestUserAction({ scenario: 'completed' });
93
- throw new UserRefusedError(false);
109
+ request.reject(new UserRefusedError(!fromUI));
94
110
  };
111
+ #signGeneric = restrictConcurrency(async ({ baseAssetName, scenario, sign }) => {
112
+ const id = randomBytes(16).toString('hex');
113
+ this.#logger.debug(`Starting signing request for ${baseAssetName} with scenario: ${scenario} and id: ${id}`);
114
+ const deferred = pDefer();
115
+ this.#signingRequest = {
116
+ id,
117
+ sign: async ({ device }) => {
118
+ await this.#updateSigningRequest({
119
+ id,
120
+ baseAssetName,
121
+ scenario,
122
+ });
123
+ await device.ensureApplicationIsOpened(baseAssetName);
124
+ return sign({ device });
125
+ },
126
+ resolve: deferred.resolve,
127
+ reject: deferred.reject,
128
+ };
129
+ void this.retrySigningRequest(id);
130
+ return deferred.promise;
131
+ });
95
132
  signTransaction = async ({ baseAssetName, unsignedTx, walletAccount, multisigData, }) => {
96
133
  const baseAsset = this.#assetsModule.getAsset(baseAssetName);
97
134
  const accountIndex = walletAccount.index;
@@ -345,8 +382,8 @@ const hardwareWalletsModuleDefinition = {
345
382
  'assetsModule',
346
383
  'logger',
347
384
  'ledgerDiscovery',
348
- 'userInterface',
349
385
  'publicKeyStore',
386
+ 'hardwareWalletSigningRequestsAtom',
350
387
  'wallet',
351
388
  'walletAccountsAtom',
352
389
  'walletAccounts',
@@ -81,9 +81,21 @@ export type GenericSignCallback = ({ device }: {
81
81
  }) => Promise<any>;
82
82
  export interface GenericSignParams {
83
83
  baseAssetName: string;
84
- scenario: string;
84
+ scenario: 'signTransaction' | 'signMessage';
85
85
  sign: GenericSignCallback;
86
86
  }
87
+ export interface SigningRequestState {
88
+ id: string;
89
+ baseAssetName?: string;
90
+ scenario: 'signTransaction' | 'signMessage' | 'error';
91
+ error?: Error;
92
+ }
93
+ export interface SigningRequest {
94
+ id: string;
95
+ sign: GenericSignCallback;
96
+ resolve: (result: any) => void;
97
+ reject: (error: Error) => void;
98
+ }
87
99
  export interface SignTransactionParams {
88
100
  baseAssetName: string;
89
101
  unsignedTx: UnsignedTransaction;
@@ -1,17 +1,19 @@
1
1
  import type { Atom } from '@exodus/atoms';
2
2
  import type { Port } from '../shared/types';
3
3
  import type { WalletAccountNameToConnectedAssetNamesMap } from '../atoms/index.js';
4
+ import type { SigningRequestState } from '../module/interfaces.js';
4
5
  declare const hardwareWalletsPluginDefinition: {
5
6
  readonly id: "hardwareWalletsPlugin";
6
7
  readonly type: "plugin";
7
- readonly factory: ({ hardwareWalletConnectedAssetNamesAtom, port, }: {
8
+ readonly factory: ({ hardwareWalletConnectedAssetNamesAtom, hardwareWalletSigningRequestsAtom, port, }: {
8
9
  hardwareWalletConnectedAssetNamesAtom: Atom<WalletAccountNameToConnectedAssetNamesMap>;
10
+ hardwareWalletSigningRequestsAtom: Atom<SigningRequestState>;
9
11
  port: Port;
10
12
  }) => {
11
13
  onUnlock: () => void;
12
14
  onLoad: () => void;
13
15
  onStop: () => void;
14
16
  };
15
- readonly dependencies: readonly ["hardwareWalletConnectedAssetNamesAtom", "port"];
17
+ readonly dependencies: readonly ["hardwareWalletConnectedAssetNamesAtom", "hardwareWalletSigningRequestsAtom", "port"];
16
18
  };
17
19
  export default hardwareWalletsPluginDefinition;
@@ -1,11 +1,16 @@
1
1
  import { createAtomObserver } from '@exodus/atoms';
2
- const createHardwareWalletsPlugin = ({ hardwareWalletConnectedAssetNamesAtom, port, }) => {
2
+ const createHardwareWalletsPlugin = ({ hardwareWalletConnectedAssetNamesAtom, hardwareWalletSigningRequestsAtom, port, }) => {
3
3
  const observers = [
4
4
  createAtomObserver({
5
5
  atom: hardwareWalletConnectedAssetNamesAtom,
6
6
  port,
7
7
  event: 'hardwareWalletConnectedAssetNames',
8
8
  }),
9
+ createAtomObserver({
10
+ atom: hardwareWalletSigningRequestsAtom,
11
+ port,
12
+ event: 'hardwareWalletSigningRequests',
13
+ }),
9
14
  ];
10
15
  observers.forEach((observer) => observer.register());
11
16
  const start = () => {
@@ -29,6 +34,10 @@ const hardwareWalletsPluginDefinition = {
29
34
  id: 'hardwareWalletsPlugin',
30
35
  type: 'plugin',
31
36
  factory: createHardwareWalletsPlugin,
32
- dependencies: ['hardwareWalletConnectedAssetNamesAtom', 'port'],
37
+ dependencies: [
38
+ 'hardwareWalletConnectedAssetNamesAtom',
39
+ 'hardwareWalletSigningRequestsAtom',
40
+ 'port',
41
+ ],
33
42
  };
34
43
  export default hardwareWalletsPluginDefinition;
@@ -1,3 +1,4 @@
1
+ import type { SigningRequestState } from '../module/interfaces.js';
1
2
  import { type HardwareWalletsState } from './initial-state.js';
2
3
  declare const hardwareWalletsReduxDefinition: {
3
4
  readonly id: "hardwareWallets";
@@ -6,14 +7,25 @@ declare const hardwareWalletsReduxDefinition: {
6
7
  readonly eventReducers: {
7
8
  readonly hardwareWalletConnectedAssetNames: (state: HardwareWalletsState, payload: boolean) => {
8
9
  walletAccountNameToConnectedAssetNamesMap: boolean;
10
+ signingRequests: SigningRequestState;
11
+ };
12
+ readonly hardwareWalletSigningRequests: (state: HardwareWalletsState, payload: SigningRequestState) => {
13
+ signingRequests: SigningRequestState;
14
+ walletAccountNameToConnectedAssetNamesMap: import("../atoms/index.js").WalletAccountNameToConnectedAssetNamesMap;
9
15
  };
10
16
  };
11
- readonly selectorDefinitions: {
17
+ readonly selectorDefinitions: ({
12
18
  readonly id: "isAssetNameConnectedForWalletAccount";
13
19
  readonly selectorFactory: (selfSelector: any) => any;
14
20
  readonly dependencies: readonly [{
15
21
  readonly selector: string;
16
22
  }];
17
- }[];
23
+ } | {
24
+ readonly id: "getSigningRequests";
25
+ readonly resultFunction: (self: HardwareWalletsState) => SigningRequestState;
26
+ readonly dependencies: readonly [{
27
+ readonly selector: string;
28
+ }];
29
+ })[];
18
30
  };
19
31
  export default hardwareWalletsReduxDefinition;
@@ -10,6 +10,10 @@ const hardwareWalletsReduxDefinition = {
10
10
  ...state,
11
11
  walletAccountNameToConnectedAssetNamesMap: payload,
12
12
  }),
13
+ hardwareWalletSigningRequests: (state, payload) => ({
14
+ ...state,
15
+ signingRequests: payload,
16
+ }),
13
17
  },
14
18
  selectorDefinitions,
15
19
  };
@@ -1,6 +1,8 @@
1
1
  import type { WalletAccountNameToConnectedAssetNamesMap } from '../atoms/index.js';
2
+ import type { SigningRequestState } from '../module/interfaces.js';
2
3
  export type HardwareWalletsState = {
3
4
  walletAccountNameToConnectedAssetNamesMap: WalletAccountNameToConnectedAssetNamesMap;
5
+ signingRequests: SigningRequestState;
4
6
  };
5
7
  declare const initialState: HardwareWalletsState;
6
8
  export default initialState;
@@ -1,4 +1,5 @@
1
1
  const initialState = {
2
2
  walletAccountNameToConnectedAssetNamesMap: Object.create(null),
3
+ signingRequests: Object.create(null),
3
4
  };
4
5
  export default initialState;
@@ -0,0 +1,9 @@
1
+ import type { HardwareWalletsState } from '../initial-state.js';
2
+ declare const assetDataSelectorDefinition: {
3
+ readonly id: "getSigningRequests";
4
+ readonly resultFunction: (self: HardwareWalletsState) => import("../../module/interfaces.js").SigningRequestState;
5
+ readonly dependencies: readonly [{
6
+ readonly selector: string;
7
+ }];
8
+ };
9
+ export default assetDataSelectorDefinition;
@@ -0,0 +1,8 @@
1
+ import { MY_STATE } from '@exodus/redux-dependency-injection';
2
+ const resultFunction = (self) => self.signingRequests;
3
+ const assetDataSelectorDefinition = {
4
+ id: 'getSigningRequests',
5
+ resultFunction,
6
+ dependencies: [{ selector: MY_STATE }],
7
+ };
8
+ export default assetDataSelectorDefinition;
@@ -1,8 +1,14 @@
1
- declare const hardwareWalletsSelectors: {
1
+ declare const hardwareWalletsSelectors: ({
2
2
  readonly id: "isAssetNameConnectedForWalletAccount";
3
3
  readonly selectorFactory: (selfSelector: any) => any;
4
4
  readonly dependencies: readonly [{
5
5
  readonly selector: string;
6
6
  }];
7
- }[];
7
+ } | {
8
+ readonly id: "getSigningRequests";
9
+ readonly resultFunction: (self: import("../initial-state.js").HardwareWalletsState) => import("../../module/interfaces.js").SigningRequestState;
10
+ readonly dependencies: readonly [{
11
+ readonly selector: string;
12
+ }];
13
+ })[];
8
14
  export default hardwareWalletsSelectors;
@@ -1,3 +1,7 @@
1
1
  import isAssetNameConnectedForWalletAccountSelectorDefinition from './isAssetNameConnectedForWalletAccount.js';
2
- const hardwareWalletsSelectors = [isAssetNameConnectedForWalletAccountSelectorDefinition];
2
+ import getSigningRequests from './getSigningRequests.js';
3
+ const hardwareWalletsSelectors = [
4
+ isAssetNameConnectedForWalletAccountSelectorDefinition,
5
+ getSigningRequests,
6
+ ];
3
7
  export default hardwareWalletsSelectors;
@@ -0,0 +1 @@
1
+ {"root":["../src/index.ts","../src/types.d.ts","../src/api/index.ts","../src/atoms/hardwareWalletSigningRequestsAtom.ts","../src/atoms/index.ts","../src/module/hardware-wallets.ts","../src/module/index.ts","../src/module/interfaces.ts","../src/plugin/index.ts","../src/redux/id.ts","../src/redux/index.ts","../src/redux/initial-state.ts","../src/redux/selectors/getSigningRequests.ts","../src/redux/selectors/index.ts","../src/redux/selectors/isAssetNameConnectedForWalletAccount.ts","../src/shared/types.d.ts"],"version":"5.8.3"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/hardware-wallets",
3
- "version": "2.0.5",
3
+ "version": "3.0.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": {
@@ -33,23 +33,24 @@
33
33
  "@exodus/bip32": "^4.0.2",
34
34
  "@exodus/crypto": "^1.0.0-rc.14",
35
35
  "@exodus/hw-common": "^3.1.0",
36
- "@exodus/models": "^12.0.1",
36
+ "@exodus/models": "^12.11.0",
37
37
  "@exodus/redux-dependency-injection": "^4.0.0",
38
38
  "@exodus/wild-emitter": "^1.1.0",
39
39
  "delay": "^5.0.0",
40
+ "make-concurrent": "^5.4.0",
40
41
  "minimalistic-assert": "^1.0.1",
42
+ "p-defer": "^4.0.1",
41
43
  "reselect": "^3.0.1"
42
44
  },
43
45
  "devDependencies": {
44
46
  "@exodus/dependency-types": "^2.1.1",
45
47
  "@exodus/key-identifier": "^1.3.0",
46
48
  "@exodus/logger": "^1.2.3",
47
- "@exodus/public-key-provider": "^4.1.1",
48
- "p-defer": "^4.0.1",
49
+ "@exodus/public-key-provider": "^4.2.0",
49
50
  "redux": "^4.2.1"
50
51
  },
51
52
  "publishConfig": {
52
53
  "access": "public"
53
54
  },
54
- "gitHead": "64cb4c29b1e7888e6e4bc4582e3aa2497f259fea"
55
+ "gitHead": "450614977e436829ea05826a4ec7265e768f3f4a"
55
56
  }