@exodus/hw-ledger 2.6.0 → 2.7.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 +7 -0
- package/lib/atoms/index.d.ts +12 -0
- package/lib/atoms/index.js +13 -0
- package/lib/index.d.ts +37 -6
- package/lib/index.js +11 -0
- package/lib/module/discovery.d.ts +6 -9
- package/lib/module/discovery.js +10 -6
- package/lib/module/types.d.ts +16 -0
- package/lib/plugin/index.d.ts +20 -0
- package/lib/plugin/index.js +59 -0
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,13 @@
|
|
|
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
|
+
## [2.7.0](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/hw-ledger@2.6.0...@exodus/hw-ledger@2.7.0) (2024-07-04)
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
- **ledger:** add `bluetoothScanningAtom` atom to indicate if scanning ([#7645](https://github.com/ExodusMovement/exodus-hydra/issues/7645)) ([bc377ea](https://github.com/ExodusMovement/exodus-hydra/commit/bc377ea7c4b1dd3a33b892791b80ea53e8ec2b58))
|
|
11
|
+
- **ledger:** support retrieving BLE status ([#7631](https://github.com/ExodusMovement/exodus-hydra/issues/7631)) ([22eebc1](https://github.com/ExodusMovement/exodus-hydra/commit/22eebc1a059c502644f515897aefd1b4ef268cad))
|
|
12
|
+
|
|
6
13
|
## [2.6.0](https://github.com/ExodusMovement/exodus-hydra/compare/@exodus/hw-ledger@2.5.1...@exodus/hw-ledger@2.6.0) (2024-07-03)
|
|
7
14
|
|
|
8
15
|
### Features
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare const bluetoothEnabledAtomDefinition: {
|
|
2
|
+
readonly id: "bluetoothEnabledAtom";
|
|
3
|
+
readonly type: "atom";
|
|
4
|
+
readonly factory: () => import("@exodus/atoms").Atom<boolean>;
|
|
5
|
+
readonly dependencies: readonly [];
|
|
6
|
+
};
|
|
7
|
+
export declare const bluetoothScanningAtomDefinition: {
|
|
8
|
+
readonly id: "bluetoothScanningAtom";
|
|
9
|
+
readonly type: "atom";
|
|
10
|
+
readonly factory: () => import("@exodus/atoms").Atom<boolean>;
|
|
11
|
+
readonly dependencies: readonly [];
|
|
12
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { createInMemoryAtom } from '@exodus/atoms';
|
|
2
|
+
export const bluetoothEnabledAtomDefinition = {
|
|
3
|
+
id: 'bluetoothEnabledAtom',
|
|
4
|
+
type: 'atom',
|
|
5
|
+
factory: () => createInMemoryAtom({ defaultValue: false }),
|
|
6
|
+
dependencies: [],
|
|
7
|
+
};
|
|
8
|
+
export const bluetoothScanningAtomDefinition = {
|
|
9
|
+
id: 'bluetoothScanningAtom',
|
|
10
|
+
type: 'atom',
|
|
11
|
+
factory: () => createInMemoryAtom({ defaultValue: false }),
|
|
12
|
+
dependencies: [],
|
|
13
|
+
};
|
package/lib/index.d.ts
CHANGED
|
@@ -1,16 +1,47 @@
|
|
|
1
1
|
import type { HwLedgerConfig } from './module/types';
|
|
2
2
|
declare const hardwareWalletLedger: ({ bluetoothScannerTimeout, }?: Partial<HwLedgerConfig>) => {
|
|
3
|
-
id:
|
|
4
|
-
definitions: {
|
|
5
|
-
definition: {
|
|
3
|
+
readonly id: "hardwareWalletLedger";
|
|
4
|
+
readonly definitions: readonly [{
|
|
5
|
+
readonly definition: {
|
|
6
6
|
readonly id: "ledgerDiscovery";
|
|
7
7
|
readonly type: "module";
|
|
8
8
|
readonly factory: (deps: import("./module").Dependencies) => import("./module").LedgerDiscovery;
|
|
9
9
|
readonly dependencies: readonly ["config", "logger", "transportsFactories"];
|
|
10
10
|
};
|
|
11
|
-
config: {
|
|
12
|
-
bluetoothScannerTimeout: number;
|
|
11
|
+
readonly config: {
|
|
12
|
+
readonly bluetoothScannerTimeout: number;
|
|
13
13
|
};
|
|
14
|
-
}
|
|
14
|
+
}, {
|
|
15
|
+
readonly definition: {
|
|
16
|
+
readonly id: "bluetoothEnabledAtom";
|
|
17
|
+
readonly type: "atom";
|
|
18
|
+
readonly factory: () => import("libraries/atoms/lib").Atom<boolean>;
|
|
19
|
+
readonly dependencies: readonly [];
|
|
20
|
+
};
|
|
21
|
+
}, {
|
|
22
|
+
readonly definition: {
|
|
23
|
+
readonly id: "bluetoothScanningAtom";
|
|
24
|
+
readonly type: "atom";
|
|
25
|
+
readonly factory: () => import("libraries/atoms/lib").Atom<boolean>;
|
|
26
|
+
readonly dependencies: readonly [];
|
|
27
|
+
};
|
|
28
|
+
}, {
|
|
29
|
+
readonly definition: {
|
|
30
|
+
readonly id: "hardwareWalletLedgerPlugin";
|
|
31
|
+
readonly type: "plugin";
|
|
32
|
+
readonly factory: ({ logger, transportsFactories, bluetoothEnabledAtom, bluetoothScanningAtom, port, }: {
|
|
33
|
+
logger: import("./shared/types").Logger;
|
|
34
|
+
transportsFactories: import("./module/types").TransportFactories;
|
|
35
|
+
bluetoothEnabledAtom: import("libraries/atoms/lib").Atom<boolean>;
|
|
36
|
+
bluetoothScanningAtom: import("libraries/atoms/lib").Atom<boolean>;
|
|
37
|
+
port: import("./shared/types").Port;
|
|
38
|
+
}) => {
|
|
39
|
+
onUnlock: () => void;
|
|
40
|
+
onLoad: () => void;
|
|
41
|
+
onStop: () => void;
|
|
42
|
+
};
|
|
43
|
+
readonly dependencies: readonly ["logger", "transportsFactories", "bluetoothEnabledAtom", "bluetoothScanningAtom", "port"];
|
|
44
|
+
};
|
|
45
|
+
}];
|
|
15
46
|
};
|
|
16
47
|
export default hardwareWalletLedger;
|
package/lib/index.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { bluetoothEnabledAtomDefinition, bluetoothScanningAtomDefinition } from './atoms';
|
|
1
2
|
import ledgerDiscoveryDefinition from './module';
|
|
3
|
+
import hardwareWalletLedgerPluginDefinition from './plugin';
|
|
2
4
|
const hardwareWalletLedger = ({ bluetoothScannerTimeout = 10000, } = {}) => {
|
|
3
5
|
return {
|
|
4
6
|
id: 'hardwareWalletLedger',
|
|
@@ -7,6 +9,15 @@ const hardwareWalletLedger = ({ bluetoothScannerTimeout = 10000, } = {}) => {
|
|
|
7
9
|
definition: ledgerDiscoveryDefinition,
|
|
8
10
|
config: { bluetoothScannerTimeout },
|
|
9
11
|
},
|
|
12
|
+
{
|
|
13
|
+
definition: bluetoothEnabledAtomDefinition,
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
definition: bluetoothScanningAtomDefinition,
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
definition: hardwareWalletLedgerPluginDefinition,
|
|
20
|
+
},
|
|
10
21
|
],
|
|
11
22
|
};
|
|
12
23
|
};
|
|
@@ -1,19 +1,16 @@
|
|
|
1
|
-
import ExodusModule from '@exodus/module';
|
|
2
1
|
import { Logger } from '../shared/types';
|
|
2
|
+
import type { Atom } from '@exodus/atoms';
|
|
3
3
|
import type { HardwareWalletDescriptor, HardwareWalletDiscovery } from '@exodus/hw-common';
|
|
4
|
-
import type {
|
|
4
|
+
import type { HwLedgerConfig, TransportFactories } from './types';
|
|
5
5
|
export type Dependencies = {
|
|
6
6
|
config: HwLedgerConfig;
|
|
7
7
|
logger: Logger;
|
|
8
|
-
transportsFactories:
|
|
9
|
-
|
|
10
|
-
bluetooth: TransportFactory;
|
|
11
|
-
tcp: TransportFactory;
|
|
12
|
-
};
|
|
8
|
+
transportsFactories: TransportFactories;
|
|
9
|
+
bluetoothScanningAtom: Atom<boolean>;
|
|
13
10
|
};
|
|
14
|
-
export declare class LedgerDiscovery
|
|
11
|
+
export declare class LedgerDiscovery implements HardwareWalletDiscovery {
|
|
15
12
|
#private;
|
|
16
|
-
constructor({ config, logger, transportsFactories }: Dependencies);
|
|
13
|
+
constructor({ config, logger, transportsFactories, bluetoothScanningAtom }: Dependencies);
|
|
17
14
|
scan: () => Promise<void>;
|
|
18
15
|
stopScan: (clearDevices?: boolean) => void;
|
|
19
16
|
list: () => Promise<HardwareWalletDescriptor[]>;
|
package/lib/module/discovery.js
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
|
-
import ExodusModule from '@exodus/module';
|
|
2
1
|
import { getInfosForServiceUuid, identifyUSBProductId } from '@exodus/ledgerhq-devices';
|
|
3
2
|
import { APDU_PORT } from './constants';
|
|
4
3
|
import { LedgerDevice } from './device';
|
|
5
4
|
import { NoDeviceFoundError, UnknownTransportError } from './errors';
|
|
6
5
|
const MODULE_ID = 'ledgerDiscovery';
|
|
7
|
-
export class LedgerDiscovery
|
|
6
|
+
export class LedgerDiscovery {
|
|
7
|
+
#logger;
|
|
8
8
|
#transportsFactories;
|
|
9
9
|
#scannerTimeout;
|
|
10
10
|
#scannerBluetooth;
|
|
11
|
+
#bluetoothScanningAtom;
|
|
11
12
|
#discoveredBluetoothDevices = Object.create(null);
|
|
12
|
-
constructor({ config, logger, transportsFactories }) {
|
|
13
|
-
|
|
13
|
+
constructor({ config, logger, transportsFactories, bluetoothScanningAtom }) {
|
|
14
|
+
this.#logger = logger;
|
|
15
|
+
this.#bluetoothScanningAtom = bluetoothScanningAtom;
|
|
14
16
|
if (!(typeof transportsFactories === 'object' &&
|
|
15
17
|
Object.keys(transportsFactories).length > 0 &&
|
|
16
18
|
Object.entries(transportsFactories).every(([transportName, transportFactory]) => ['usb', 'bluetooth', 'tcp'].includes(transportName) &&
|
|
@@ -36,19 +38,20 @@ export class LedgerDiscovery extends ExodusModule {
|
|
|
36
38
|
}
|
|
37
39
|
},
|
|
38
40
|
error: (error) => {
|
|
39
|
-
this.
|
|
41
|
+
this.#logger.error(`an error occured while scanning for bluetooth devices "${error.message}"`);
|
|
40
42
|
this.stopScan();
|
|
41
43
|
reject(error);
|
|
42
44
|
},
|
|
43
45
|
complete: () => { },
|
|
44
46
|
});
|
|
47
|
+
this.#bluetoothScanningAtom.set(true);
|
|
45
48
|
setTimeout(() => {
|
|
46
49
|
this.stopScan();
|
|
47
50
|
resolve();
|
|
48
51
|
}, this.#scannerTimeout);
|
|
49
52
|
}
|
|
50
53
|
else {
|
|
51
|
-
this.
|
|
54
|
+
this.#logger.error(`Attempted to perform scan without having bluetooth transport factory`);
|
|
52
55
|
reject(new Error(`Attempted to perform scan without having bluetooth transport factory`));
|
|
53
56
|
}
|
|
54
57
|
});
|
|
@@ -58,6 +61,7 @@ export class LedgerDiscovery extends ExodusModule {
|
|
|
58
61
|
this.#discoveredBluetoothDevices = Object.create(null);
|
|
59
62
|
}
|
|
60
63
|
if (this.#scannerBluetooth) {
|
|
64
|
+
this.#bluetoothScanningAtom.set(false);
|
|
61
65
|
this.#scannerBluetooth.unsubscribe();
|
|
62
66
|
this.#scannerBluetooth = undefined;
|
|
63
67
|
}
|
package/lib/module/types.d.ts
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
import type Transport from '@ledgerhq/hw-transport';
|
|
2
|
+
import type { TransportTypes } from '@exodus/hw-common';
|
|
3
|
+
import type { Subscription } from '@ledgerhq/hw-transport';
|
|
2
4
|
export type TransportFactory = typeof Transport;
|
|
5
|
+
export type TransportFactories = Partial<Record<TransportTypes, TransportFactory>> & {
|
|
6
|
+
bluetooth?: TransportFactory & {
|
|
7
|
+
observeAvailability?: (observer: {
|
|
8
|
+
next: (available: boolean) => void;
|
|
9
|
+
error: (err: Error) => void;
|
|
10
|
+
}) => Subscription;
|
|
11
|
+
observeState?: (observer: {
|
|
12
|
+
next: (evt: {
|
|
13
|
+
available: boolean;
|
|
14
|
+
}) => void;
|
|
15
|
+
error: (err: Error) => void;
|
|
16
|
+
}) => Subscription;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
3
19
|
export type HwLedgerConfig = {
|
|
4
20
|
bluetoothScannerTimeout: number;
|
|
5
21
|
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Atom } from '@exodus/atoms';
|
|
2
|
+
import type { TransportFactories } from '../module/types';
|
|
3
|
+
import type { Logger, Port } from '../shared/types';
|
|
4
|
+
declare const hardwareWalletLedgerPluginDefinition: {
|
|
5
|
+
readonly id: "hardwareWalletLedgerPlugin";
|
|
6
|
+
readonly type: "plugin";
|
|
7
|
+
readonly factory: ({ logger, transportsFactories, bluetoothEnabledAtom, bluetoothScanningAtom, port, }: {
|
|
8
|
+
logger: Logger;
|
|
9
|
+
transportsFactories: TransportFactories;
|
|
10
|
+
bluetoothEnabledAtom: Atom<boolean>;
|
|
11
|
+
bluetoothScanningAtom: Atom<boolean>;
|
|
12
|
+
port: Port;
|
|
13
|
+
}) => {
|
|
14
|
+
onUnlock: () => void;
|
|
15
|
+
onLoad: () => void;
|
|
16
|
+
onStop: () => void;
|
|
17
|
+
};
|
|
18
|
+
readonly dependencies: readonly ["logger", "transportsFactories", "bluetoothEnabledAtom", "bluetoothScanningAtom", "port"];
|
|
19
|
+
};
|
|
20
|
+
export default hardwareWalletLedgerPluginDefinition;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { createAtomObserver } from '@exodus/atoms';
|
|
2
|
+
const createHardwareWalletLedgerPlugin = ({ logger, transportsFactories, bluetoothEnabledAtom, bluetoothScanningAtom, port, }) => {
|
|
3
|
+
let subscription;
|
|
4
|
+
const observers = [
|
|
5
|
+
createAtomObserver({ atom: bluetoothEnabledAtom, port, event: 'bluetoothEnabled' }),
|
|
6
|
+
createAtomObserver({ atom: bluetoothScanningAtom, port, event: 'bluetoothScanning' }),
|
|
7
|
+
];
|
|
8
|
+
observers.forEach((observer) => observer.register());
|
|
9
|
+
const start = () => {
|
|
10
|
+
if (!transportsFactories.bluetooth)
|
|
11
|
+
return;
|
|
12
|
+
if (subscription)
|
|
13
|
+
return;
|
|
14
|
+
if (transportsFactories.bluetooth.observeState) {
|
|
15
|
+
subscription = transportsFactories.bluetooth.observeState({
|
|
16
|
+
next: (e) => {
|
|
17
|
+
bluetoothEnabledAtom.set(!!e.available);
|
|
18
|
+
},
|
|
19
|
+
error: (error) => logger.error(error),
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
else if (transportsFactories.bluetooth.observeAvailability) {
|
|
23
|
+
subscription = transportsFactories.bluetooth.observeAvailability({
|
|
24
|
+
next: (available) => {
|
|
25
|
+
bluetoothEnabledAtom.set(available);
|
|
26
|
+
},
|
|
27
|
+
error: (error) => logger.error(error),
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
observers.forEach((observer) => observer.start());
|
|
31
|
+
};
|
|
32
|
+
const stop = () => {
|
|
33
|
+
observers.forEach((observer) => observer.unregister());
|
|
34
|
+
subscription?.unsubscribe();
|
|
35
|
+
};
|
|
36
|
+
const onUnlock = () => {
|
|
37
|
+
start();
|
|
38
|
+
};
|
|
39
|
+
const onLoad = () => {
|
|
40
|
+
start();
|
|
41
|
+
};
|
|
42
|
+
const onStop = () => {
|
|
43
|
+
stop();
|
|
44
|
+
};
|
|
45
|
+
return { onUnlock, onLoad, onStop };
|
|
46
|
+
};
|
|
47
|
+
const hardwareWalletLedgerPluginDefinition = {
|
|
48
|
+
id: 'hardwareWalletLedgerPlugin',
|
|
49
|
+
type: 'plugin',
|
|
50
|
+
factory: createHardwareWalletLedgerPlugin,
|
|
51
|
+
dependencies: [
|
|
52
|
+
'logger',
|
|
53
|
+
'transportsFactories',
|
|
54
|
+
'bluetoothEnabledAtom',
|
|
55
|
+
'bluetoothScanningAtom',
|
|
56
|
+
'port',
|
|
57
|
+
],
|
|
58
|
+
};
|
|
59
|
+
export default hardwareWalletLedgerPluginDefinition;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/hw-ledger",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.0",
|
|
4
4
|
"description": "The ledger module",
|
|
5
5
|
"author": "Exodus Movement, Inc.",
|
|
6
6
|
"repository": {
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"prepublishOnly": "yarn run -T build --scope @exodus/hw-ledger"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
+
"@exodus/atoms": "^7.5.1",
|
|
33
34
|
"@exodus/bip322-js": "^1.1.0-exodus.4",
|
|
34
35
|
"@exodus/bitcoinjs-lib": "^6.1.5-exodus.0",
|
|
35
36
|
"@exodus/ethersproject-transactions": "^5.4.2-exodus.0",
|
|
@@ -69,5 +70,5 @@
|
|
|
69
70
|
"ts-jest": "^29.0.3",
|
|
70
71
|
"typescript": "^4.7.3"
|
|
71
72
|
},
|
|
72
|
-
"gitHead": "
|
|
73
|
+
"gitHead": "c53411aed8e084439cc9d1a5450fa65266f834ab"
|
|
73
74
|
}
|