@ledgerhq/hw-transport-node-hid-singleton 6.28.18-next.0 → 6.29.0-nightly.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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +27 -0
- package/README.md +23 -3
- package/lib/TransportNodeHid.d.ts +13 -2
- package/lib/TransportNodeHid.d.ts.map +1 -1
- package/lib/TransportNodeHid.js +19 -9
- package/lib/TransportNodeHid.js.map +1 -1
- package/lib/listenDevices.d.ts.map +1 -1
- package/lib/listenDevices.js +4 -2
- package/lib/listenDevices.js.map +1 -1
- package/lib-es/TransportNodeHid.d.ts +13 -2
- package/lib-es/TransportNodeHid.d.ts.map +1 -1
- package/lib-es/TransportNodeHid.js +20 -10
- package/lib-es/TransportNodeHid.js.map +1 -1
- package/lib-es/listenDevices.d.ts.map +1 -1
- package/lib-es/listenDevices.js +5 -3
- package/lib-es/listenDevices.js.map +1 -1
- package/package.json +6 -6
- package/src/TransportNodeHid.ts +31 -9
- package/src/listenDevices.ts +6 -3
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
|
|
2
|
-
> @ledgerhq/hw-transport-node-hid-singleton@6.28.
|
|
2
|
+
> @ledgerhq/hw-transport-node-hid-singleton@6.28.18 build /home/runner/work/ledger-live/ledger-live/libs/ledgerjs/packages/hw-transport-node-hid-singleton
|
|
3
3
|
> tsc && tsc -m ES6 --outDir lib-es
|
|
4
4
|
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# @ledgerhq/hw-transport-node-hid-singleton
|
|
2
2
|
|
|
3
|
+
## 6.29.0-nightly.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#4709](https://github.com/LedgerHQ/ledger-live/pull/4709) [`9e2d32aec4`](https://github.com/LedgerHQ/ledger-live/commit/9e2d32aec4ebd8774880f94e3ef0e805ebb172ac) Thanks [@alexandremgo](https://github.com/alexandremgo)! - feat: usage of new tracing system
|
|
8
|
+
|
|
9
|
+
The tracing helps keeping a context (for ex a `job id`) that is propagated to other logs,
|
|
10
|
+
creating a (simple) tracing span
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- Updated dependencies [[`9e2d32aec4`](https://github.com/LedgerHQ/ledger-live/commit/9e2d32aec4ebd8774880f94e3ef0e805ebb172ac), [`9e2d32aec4`](https://github.com/LedgerHQ/ledger-live/commit/9e2d32aec4ebd8774880f94e3ef0e805ebb172ac)]:
|
|
15
|
+
- @ledgerhq/logs@6.11.0-nightly.0
|
|
16
|
+
- @ledgerhq/hw-transport-node-hid-noevents@6.28.0-nightly.0
|
|
17
|
+
- @ledgerhq/hw-transport@6.29.0-nightly.0
|
|
18
|
+
- @ledgerhq/devices@8.0.8-nightly.0
|
|
19
|
+
|
|
20
|
+
## 6.28.18
|
|
21
|
+
|
|
22
|
+
### Patch Changes
|
|
23
|
+
|
|
24
|
+
- Updated dependencies [[`a61a43fc47`](https://github.com/LedgerHQ/ledger-live/commit/a61a43fc47399e969fa68539de6af51bfa41e921), [`3455944496`](https://github.com/LedgerHQ/ledger-live/commit/34559444969ce1571ff4c54f33feb7f3fb59a33a)]:
|
|
25
|
+
- @ledgerhq/errors@6.14.0
|
|
26
|
+
- @ledgerhq/devices@8.0.7
|
|
27
|
+
- @ledgerhq/hw-transport@6.28.8
|
|
28
|
+
- @ledgerhq/hw-transport-node-hid-noevents@6.27.19
|
|
29
|
+
|
|
3
30
|
## 6.28.18-next.0
|
|
4
31
|
|
|
5
32
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -30,16 +30,18 @@ For a smooth and quick integration:
|
|
|
30
30
|
#### Table of Contents
|
|
31
31
|
|
|
32
32
|
* [TransportNodeHidSingleton](#transportnodehidsingleton)
|
|
33
|
+
* [Parameters](#parameters)
|
|
33
34
|
* [Examples](#examples)
|
|
34
35
|
* [exchange](#exchange)
|
|
35
|
-
* [Parameters](#parameters)
|
|
36
|
+
* [Parameters](#parameters-1)
|
|
36
37
|
* [isSupported](#issupported)
|
|
37
38
|
* [list](#list)
|
|
38
39
|
* [listen](#listen)
|
|
39
|
-
* [Parameters](#parameters-
|
|
40
|
+
* [Parameters](#parameters-2)
|
|
40
41
|
* [autoDisconnect](#autodisconnect)
|
|
41
42
|
* [disconnect](#disconnect)
|
|
42
43
|
* [open](#open)
|
|
44
|
+
* [Parameters](#parameters-3)
|
|
43
45
|
|
|
44
46
|
### TransportNodeHidSingleton
|
|
45
47
|
|
|
@@ -47,6 +49,13 @@ For a smooth and quick integration:
|
|
|
47
49
|
|
|
48
50
|
node-hid Transport implementation
|
|
49
51
|
|
|
52
|
+
#### Parameters
|
|
53
|
+
|
|
54
|
+
* `device` **HID.HID**
|
|
55
|
+
* `$1` **{context: TraceContext?}** (optional, default `{}`)
|
|
56
|
+
|
|
57
|
+
* `$1.context`
|
|
58
|
+
|
|
50
59
|
#### Examples
|
|
51
60
|
|
|
52
61
|
```javascript
|
|
@@ -89,6 +98,17 @@ globally disconnect the transport singleton
|
|
|
89
98
|
|
|
90
99
|
#### open
|
|
91
100
|
|
|
92
|
-
|
|
101
|
+
Connects to the first Ledger device connected via USB
|
|
102
|
+
|
|
103
|
+
Reusing the same TransportNodeHidSingleton instance until a disconnection happens.
|
|
104
|
+
Pitfall: this implementation only handles 1 device connected via USB
|
|
105
|
+
|
|
106
|
+
Legacy: `_descriptor` is needed to follow the Transport definition
|
|
107
|
+
|
|
108
|
+
##### Parameters
|
|
109
|
+
|
|
110
|
+
* `_descriptor` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
|
|
111
|
+
* `_timeoutMs` **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?**
|
|
112
|
+
* `context` **TraceContext?**
|
|
93
113
|
|
|
94
114
|
Returns **[Promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)<[TransportNodeHidSingleton](#transportnodehidsingleton)>**
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
+
import HID from "node-hid";
|
|
2
3
|
import TransportNodeHidNoEvents from "@ledgerhq/hw-transport-node-hid-noevents";
|
|
3
4
|
import type { Observer, DescriptorEvent, Subscription } from "@ledgerhq/hw-transport";
|
|
5
|
+
import { TraceContext } from "@ledgerhq/logs";
|
|
4
6
|
export type ListenDescriptorEvent = DescriptorEvent<any>;
|
|
5
7
|
/**
|
|
6
8
|
* node-hid Transport implementation
|
|
@@ -11,6 +13,9 @@ export type ListenDescriptorEvent = DescriptorEvent<any>;
|
|
|
11
13
|
*/
|
|
12
14
|
export default class TransportNodeHidSingleton extends TransportNodeHidNoEvents {
|
|
13
15
|
preventAutoDisconnect: boolean;
|
|
16
|
+
constructor(device: HID.HID, { context }?: {
|
|
17
|
+
context?: TraceContext;
|
|
18
|
+
});
|
|
14
19
|
/**
|
|
15
20
|
*
|
|
16
21
|
*/
|
|
@@ -31,12 +36,18 @@ export default class TransportNodeHidSingleton extends TransportNodeHidNoEvents
|
|
|
31
36
|
*/
|
|
32
37
|
static disconnect(): Promise<void>;
|
|
33
38
|
/**
|
|
34
|
-
*
|
|
39
|
+
* Connects to the first Ledger device connected via USB
|
|
40
|
+
*
|
|
41
|
+
* Reusing the same TransportNodeHidSingleton instance until a disconnection happens.
|
|
42
|
+
* Pitfall: this implementation only handles 1 device connected via USB
|
|
43
|
+
*
|
|
44
|
+
* Legacy: `_descriptor` is needed to follow the Transport definition
|
|
35
45
|
*/
|
|
36
|
-
static open(): Promise<TransportNodeHidSingleton>;
|
|
46
|
+
static open(_descriptor: string, _timeoutMs?: number, context?: TraceContext): Promise<TransportNodeHidSingleton>;
|
|
37
47
|
setAllowAutoDisconnect(allow: boolean): void;
|
|
38
48
|
/**
|
|
39
49
|
* Exchange with the device using APDU protocol.
|
|
50
|
+
*
|
|
40
51
|
* @param apdu
|
|
41
52
|
* @returns a promise of apdu response
|
|
42
53
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TransportNodeHid.d.ts","sourceRoot":"","sources":["../src/TransportNodeHid.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"TransportNodeHid.d.ts","sourceRoot":"","sources":["../src/TransportNodeHid.ts"],"names":[],"mappings":";AAAA,OAAO,GAAG,MAAM,UAAU,CAAC;AAC3B,OAAO,wBAAwC,MAAM,0CAA0C,CAAC;AAChG,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtF,OAAO,EAAe,YAAY,EAAO,MAAM,gBAAgB,CAAC;AAyBhE,MAAM,MAAM,qBAAqB,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;AAEzD;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,OAAO,yBAA0B,SAAQ,wBAAwB;IAC7E,qBAAqB,UAAS;gBAElB,MAAM,EAAE,GAAG,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,GAAE;QAAE,OAAO,CAAC,EAAE,YAAY,CAAA;KAAO;IAIzE;;OAEG;IACH,MAAM,CAAC,WAAW,yBAAwC;IAE1D;;OAEG;IACH,MAAM,CAAC,IAAI,qBAAiC;IAE5C;OACG;IACH,MAAM,CAAC,MAAM,aAAc,SAAS,qBAAqB,CAAC,KAAG,YAAY,CAqDvE;IAEF;;OAEG;WACU,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAW5C;;OAEG;WACU,UAAU;IASvB;;;;;;;OAOG;IACH,MAAM,CAAC,IAAI,CACT,WAAW,EAAE,MAAM,EACnB,UAAU,CAAC,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,YAAY,GACrB,OAAO,CAAC,yBAAyB,CAAC;IAyCrC,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAI5C;;;;;OAKG;IACG,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAO7C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAMvB"}
|
package/lib/TransportNodeHid.js
CHANGED
|
@@ -41,6 +41,7 @@ const logs_1 = require("@ledgerhq/logs");
|
|
|
41
41
|
const devices_1 = require("@ledgerhq/devices");
|
|
42
42
|
const errors_1 = require("@ledgerhq/errors");
|
|
43
43
|
const listenDevices_1 = require("./listenDevices");
|
|
44
|
+
const LOG_TYPE = "hid-verbose";
|
|
44
45
|
let transportInstance;
|
|
45
46
|
const DISCONNECT_TIMEOUT = 5000;
|
|
46
47
|
let disconnectTimeout;
|
|
@@ -61,8 +62,8 @@ const setDisconnectTimeout = () => {
|
|
|
61
62
|
* TransportNodeHid.create().then(transport => ...)
|
|
62
63
|
*/
|
|
63
64
|
class TransportNodeHidSingleton extends hw_transport_node_hid_noevents_1.default {
|
|
64
|
-
constructor() {
|
|
65
|
-
super(
|
|
65
|
+
constructor(device, { context } = {}) {
|
|
66
|
+
super(device, { context, logType: LOG_TYPE });
|
|
66
67
|
this.preventAutoDisconnect = false;
|
|
67
68
|
}
|
|
68
69
|
/**
|
|
@@ -95,22 +96,30 @@ class TransportNodeHidSingleton extends hw_transport_node_hid_noevents_1.default
|
|
|
95
96
|
});
|
|
96
97
|
}
|
|
97
98
|
/**
|
|
98
|
-
*
|
|
99
|
+
* Connects to the first Ledger device connected via USB
|
|
100
|
+
*
|
|
101
|
+
* Reusing the same TransportNodeHidSingleton instance until a disconnection happens.
|
|
102
|
+
* Pitfall: this implementation only handles 1 device connected via USB
|
|
103
|
+
*
|
|
104
|
+
* Legacy: `_descriptor` is needed to follow the Transport definition
|
|
99
105
|
*/
|
|
100
|
-
static open() {
|
|
106
|
+
static open(_descriptor, _timeoutMs, context) {
|
|
107
|
+
const tracer = new logs_1.LocalTracer(LOG_TYPE, context);
|
|
101
108
|
clearDisconnectTimeout();
|
|
102
109
|
return Promise.resolve().then(() => {
|
|
103
110
|
if (transportInstance) {
|
|
104
|
-
|
|
111
|
+
tracer.trace("Reusing already opened transport instance");
|
|
105
112
|
return transportInstance;
|
|
106
113
|
}
|
|
107
114
|
const device = (0, hw_transport_node_hid_noevents_1.getDevices)()[0];
|
|
108
115
|
if (!device)
|
|
109
116
|
throw new errors_1.CantOpenDevice("no device found");
|
|
110
|
-
|
|
111
|
-
transportInstance = new TransportNodeHidSingleton(new node_hid_1.default.HID(device.path)
|
|
117
|
+
tracer.trace("Found a device, creating HID transport instance ...", { device });
|
|
118
|
+
transportInstance = new TransportNodeHidSingleton(new node_hid_1.default.HID(device.path), {
|
|
119
|
+
context,
|
|
120
|
+
});
|
|
112
121
|
const unlisten = (0, listenDevices_1.listenDevices)(() => { }, () => {
|
|
113
|
-
//
|
|
122
|
+
// Assumes any ledger disconnection concerns current transport
|
|
114
123
|
if (transportInstance) {
|
|
115
124
|
transportInstance.emit("disconnect");
|
|
116
125
|
}
|
|
@@ -118,7 +127,7 @@ class TransportNodeHidSingleton extends hw_transport_node_hid_noevents_1.default
|
|
|
118
127
|
const onDisconnect = () => {
|
|
119
128
|
if (!transportInstance)
|
|
120
129
|
return;
|
|
121
|
-
|
|
130
|
+
tracer.trace("Device was disconnected, clearing transport instance ...");
|
|
122
131
|
transportInstance.off("disconnect", onDisconnect);
|
|
123
132
|
transportInstance = null;
|
|
124
133
|
unlisten();
|
|
@@ -132,6 +141,7 @@ class TransportNodeHidSingleton extends hw_transport_node_hid_noevents_1.default
|
|
|
132
141
|
}
|
|
133
142
|
/**
|
|
134
143
|
* Exchange with the device using APDU protocol.
|
|
144
|
+
*
|
|
135
145
|
* @param apdu
|
|
136
146
|
* @returns a promise of apdu response
|
|
137
147
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TransportNodeHid.js","sourceRoot":"","sources":["../src/TransportNodeHid.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,wDAA2B;AAC3B,2GAAgG;AAEhG,
|
|
1
|
+
{"version":3,"file":"TransportNodeHid.js","sourceRoot":"","sources":["../src/TransportNodeHid.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"listenDevices.d.ts","sourceRoot":"","sources":["../src/listenDevices.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"listenDevices.d.ts","sourceRoot":"","sources":["../src/listenDevices.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,MAAM,GAAG;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC;AAMF,eAAO,MAAM,cAAc,MAAO,MAAM,SAEvC,CAAC;AAiBF,eAAO,MAAM,aAAa,iBAAkB,MAAM,KAAK,IAAI,mBAAmB,MAAM,KAAK,IAAI,eAqC5F,CAAC"}
|
package/lib/listenDevices.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.listenDevices = exports.setUsbDebounce = void 0;
|
|
|
4
4
|
const usb_1 = require("usb");
|
|
5
5
|
const devices_1 = require("@ledgerhq/devices");
|
|
6
6
|
const logs_1 = require("@ledgerhq/logs");
|
|
7
|
+
const LOG_TYPE = "usb-detection";
|
|
7
8
|
const deviceToLog = ({ deviceDescriptor: { idProduct }, busNumber, deviceAddress }) => `productId=${idProduct} busNumber=${busNumber} deviceAddress=${deviceAddress}`;
|
|
8
9
|
let usbDebounce = 1000;
|
|
9
10
|
const setUsbDebounce = (n) => {
|
|
@@ -21,11 +22,12 @@ const mapRawDevice = ({ busNumber: locationId, deviceAddress, deviceDescriptor:
|
|
|
21
22
|
});
|
|
22
23
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
23
24
|
const listenDevices = (onAdd, onRemove) => {
|
|
25
|
+
const tracer = new logs_1.LocalTracer(LOG_TYPE, { function: "listenDevices " });
|
|
24
26
|
let timeout;
|
|
25
27
|
const add = device => {
|
|
26
28
|
if (device.deviceDescriptor.idVendor !== devices_1.ledgerUSBVendorId)
|
|
27
29
|
return;
|
|
28
|
-
|
|
30
|
+
tracer.trace(`add: ${deviceToLog(device)}`, { device });
|
|
29
31
|
if (!timeout) {
|
|
30
32
|
// a time is needed for the device to actually be connectable over HID..
|
|
31
33
|
// we also take this time to not emit the device yet and potentially cancel it if a remove happens.
|
|
@@ -38,7 +40,7 @@ const listenDevices = (onAdd, onRemove) => {
|
|
|
38
40
|
const remove = device => {
|
|
39
41
|
if (device.deviceDescriptor.idVendor !== devices_1.ledgerUSBVendorId)
|
|
40
42
|
return;
|
|
41
|
-
|
|
43
|
+
tracer.trace(`remove: ${deviceToLog(device)}`, { device });
|
|
42
44
|
if (timeout) {
|
|
43
45
|
clearTimeout(timeout);
|
|
44
46
|
timeout = null;
|
package/lib/listenDevices.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"listenDevices.js","sourceRoot":"","sources":["../src/listenDevices.ts"],"names":[],"mappings":";;;AAAA,6BAA0B;AAC1B,+CAAsD;AACtD,
|
|
1
|
+
{"version":3,"file":"listenDevices.js","sourceRoot":"","sources":["../src/listenDevices.ts"],"names":[],"mappings":";;;AAAA,6BAA0B;AAC1B,+CAAsD;AACtD,yCAA6C;AAE7C,MAAM,QAAQ,GAAG,eAAe,CAAC;AAYjC,MAAM,WAAW,GAAG,CAAC,EAAE,gBAAgB,EAAE,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,aAAa,EAAE,EAAE,EAAE,CACpF,aAAa,SAAS,cAAc,SAAS,kBAAkB,aAAa,EAAE,CAAC;AAEjF,IAAI,WAAW,GAAG,IAAI,CAAC;AAChB,MAAM,cAAc,GAAG,CAAC,CAAS,EAAE,EAAE;IAC1C,WAAW,GAAG,CAAC,CAAC;AAClB,CAAC,CAAC;AAFW,QAAA,cAAc,kBAEzB;AAEF,MAAM,YAAY,GAAG,CAAC,EACpB,SAAS,EAAE,UAAU,EACrB,aAAa,EACb,gBAAgB,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,YAAY,EAAE,GAChF,EAAU,EAAE,CAAC,CAAC;IACzB,UAAU;IACV,QAAQ;IACR,SAAS;IACT,UAAU,EAAE,EAAE;IACd,YAAY,EAAE,EAAE;IAChB,YAAY;IACZ,aAAa;CACd,CAAC,CAAC;AAEH,6EAA6E;AACtE,MAAM,aAAa,GAAG,CAAC,KAA6B,EAAE,QAAgC,EAAE,EAAE;IAC/F,MAAM,MAAM,GAAG,IAAI,kBAAW,CAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAC,CAAC;IACzE,IAAI,OAAO,CAAC;IAEZ,MAAM,GAAG,GAAG,MAAM,CAAC,EAAE;QACnB,IAAI,MAAM,CAAC,gBAAgB,CAAC,QAAQ,KAAK,2BAAiB;YAAE,OAAO;QACnE,MAAM,CAAC,KAAK,CAAC,QAAQ,WAAW,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QAExD,IAAI,CAAC,OAAO,EAAE;YACZ,wEAAwE;YACxE,mGAAmG;YACnG,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;gBACxB,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC;gBAC5B,OAAO,GAAG,IAAI,CAAC;YACjB,CAAC,EAAE,WAAW,CAAC,CAAC;SACjB;IACH,CAAC,CAAC;IAEF,MAAM,MAAM,GAAG,MAAM,CAAC,EAAE;QACtB,IAAI,MAAM,CAAC,gBAAgB,CAAC,QAAQ,KAAK,2BAAiB;YAAE,OAAO;QACnE,MAAM,CAAC,KAAK,CAAC,WAAW,WAAW,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QAE3D,IAAI,OAAO,EAAE;YACX,YAAY,CAAC,OAAO,CAAC,CAAC;YACtB,OAAO,GAAG,IAAI,CAAC;SAChB;aAAM;YACL,QAAQ,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC;SAChC;IACH,CAAC,CAAC;IAEF,SAAG,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IACtB,SAAG,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAEzB,OAAO,GAAG,EAAE;QACV,IAAI,OAAO;YAAE,YAAY,CAAC,OAAO,CAAC,CAAC;QACnC,SAAG,CAAC,kBAAkB,EAAE,CAAC;IAC3B,CAAC,CAAC;AACJ,CAAC,CAAC;AArCW,QAAA,aAAa,iBAqCxB;AAEF,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE;IACtB,SAAG,CAAC,kBAAkB,EAAE,CAAC;AAC3B,CAAC,CAAC,CAAC"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
+
import HID from "node-hid";
|
|
2
3
|
import TransportNodeHidNoEvents from "@ledgerhq/hw-transport-node-hid-noevents";
|
|
3
4
|
import type { Observer, DescriptorEvent, Subscription } from "@ledgerhq/hw-transport";
|
|
5
|
+
import { TraceContext } from "@ledgerhq/logs";
|
|
4
6
|
export type ListenDescriptorEvent = DescriptorEvent<any>;
|
|
5
7
|
/**
|
|
6
8
|
* node-hid Transport implementation
|
|
@@ -11,6 +13,9 @@ export type ListenDescriptorEvent = DescriptorEvent<any>;
|
|
|
11
13
|
*/
|
|
12
14
|
export default class TransportNodeHidSingleton extends TransportNodeHidNoEvents {
|
|
13
15
|
preventAutoDisconnect: boolean;
|
|
16
|
+
constructor(device: HID.HID, { context }?: {
|
|
17
|
+
context?: TraceContext;
|
|
18
|
+
});
|
|
14
19
|
/**
|
|
15
20
|
*
|
|
16
21
|
*/
|
|
@@ -31,12 +36,18 @@ export default class TransportNodeHidSingleton extends TransportNodeHidNoEvents
|
|
|
31
36
|
*/
|
|
32
37
|
static disconnect(): Promise<void>;
|
|
33
38
|
/**
|
|
34
|
-
*
|
|
39
|
+
* Connects to the first Ledger device connected via USB
|
|
40
|
+
*
|
|
41
|
+
* Reusing the same TransportNodeHidSingleton instance until a disconnection happens.
|
|
42
|
+
* Pitfall: this implementation only handles 1 device connected via USB
|
|
43
|
+
*
|
|
44
|
+
* Legacy: `_descriptor` is needed to follow the Transport definition
|
|
35
45
|
*/
|
|
36
|
-
static open(): Promise<TransportNodeHidSingleton>;
|
|
46
|
+
static open(_descriptor: string, _timeoutMs?: number, context?: TraceContext): Promise<TransportNodeHidSingleton>;
|
|
37
47
|
setAllowAutoDisconnect(allow: boolean): void;
|
|
38
48
|
/**
|
|
39
49
|
* Exchange with the device using APDU protocol.
|
|
50
|
+
*
|
|
40
51
|
* @param apdu
|
|
41
52
|
* @returns a promise of apdu response
|
|
42
53
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TransportNodeHid.d.ts","sourceRoot":"","sources":["../src/TransportNodeHid.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"TransportNodeHid.d.ts","sourceRoot":"","sources":["../src/TransportNodeHid.ts"],"names":[],"mappings":";AAAA,OAAO,GAAG,MAAM,UAAU,CAAC;AAC3B,OAAO,wBAAwC,MAAM,0CAA0C,CAAC;AAChG,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtF,OAAO,EAAe,YAAY,EAAO,MAAM,gBAAgB,CAAC;AAyBhE,MAAM,MAAM,qBAAqB,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;AAEzD;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,OAAO,yBAA0B,SAAQ,wBAAwB;IAC7E,qBAAqB,UAAS;gBAElB,MAAM,EAAE,GAAG,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,GAAE;QAAE,OAAO,CAAC,EAAE,YAAY,CAAA;KAAO;IAIzE;;OAEG;IACH,MAAM,CAAC,WAAW,yBAAwC;IAE1D;;OAEG;IACH,MAAM,CAAC,IAAI,qBAAiC;IAE5C;OACG;IACH,MAAM,CAAC,MAAM,aAAc,SAAS,qBAAqB,CAAC,KAAG,YAAY,CAqDvE;IAEF;;OAEG;WACU,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAW5C;;OAEG;WACU,UAAU;IASvB;;;;;;;OAOG;IACH,MAAM,CAAC,IAAI,CACT,WAAW,EAAE,MAAM,EACnB,UAAU,CAAC,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,YAAY,GACrB,OAAO,CAAC,yBAAyB,CAAC;IAyCrC,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAI5C;;;;;OAKG;IACG,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAO7C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAMvB"}
|
|
@@ -9,10 +9,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
};
|
|
10
10
|
import HID from "node-hid";
|
|
11
11
|
import TransportNodeHidNoEvents, { getDevices } from "@ledgerhq/hw-transport-node-hid-noevents";
|
|
12
|
-
import { log } from "@ledgerhq/logs";
|
|
12
|
+
import { LocalTracer, log } from "@ledgerhq/logs";
|
|
13
13
|
import { identifyUSBProductId } from "@ledgerhq/devices";
|
|
14
14
|
import { CantOpenDevice } from "@ledgerhq/errors";
|
|
15
15
|
import { listenDevices } from "./listenDevices";
|
|
16
|
+
const LOG_TYPE = "hid-verbose";
|
|
16
17
|
let transportInstance;
|
|
17
18
|
const DISCONNECT_TIMEOUT = 5000;
|
|
18
19
|
let disconnectTimeout;
|
|
@@ -33,8 +34,8 @@ const setDisconnectTimeout = () => {
|
|
|
33
34
|
* TransportNodeHid.create().then(transport => ...)
|
|
34
35
|
*/
|
|
35
36
|
class TransportNodeHidSingleton extends TransportNodeHidNoEvents {
|
|
36
|
-
constructor() {
|
|
37
|
-
super(
|
|
37
|
+
constructor(device, { context } = {}) {
|
|
38
|
+
super(device, { context, logType: LOG_TYPE });
|
|
38
39
|
this.preventAutoDisconnect = false;
|
|
39
40
|
}
|
|
40
41
|
/**
|
|
@@ -67,22 +68,30 @@ class TransportNodeHidSingleton extends TransportNodeHidNoEvents {
|
|
|
67
68
|
});
|
|
68
69
|
}
|
|
69
70
|
/**
|
|
70
|
-
*
|
|
71
|
+
* Connects to the first Ledger device connected via USB
|
|
72
|
+
*
|
|
73
|
+
* Reusing the same TransportNodeHidSingleton instance until a disconnection happens.
|
|
74
|
+
* Pitfall: this implementation only handles 1 device connected via USB
|
|
75
|
+
*
|
|
76
|
+
* Legacy: `_descriptor` is needed to follow the Transport definition
|
|
71
77
|
*/
|
|
72
|
-
static open() {
|
|
78
|
+
static open(_descriptor, _timeoutMs, context) {
|
|
79
|
+
const tracer = new LocalTracer(LOG_TYPE, context);
|
|
73
80
|
clearDisconnectTimeout();
|
|
74
81
|
return Promise.resolve().then(() => {
|
|
75
82
|
if (transportInstance) {
|
|
76
|
-
|
|
83
|
+
tracer.trace("Reusing already opened transport instance");
|
|
77
84
|
return transportInstance;
|
|
78
85
|
}
|
|
79
86
|
const device = getDevices()[0];
|
|
80
87
|
if (!device)
|
|
81
88
|
throw new CantOpenDevice("no device found");
|
|
82
|
-
|
|
83
|
-
transportInstance = new TransportNodeHidSingleton(new HID.HID(device.path)
|
|
89
|
+
tracer.trace("Found a device, creating HID transport instance ...", { device });
|
|
90
|
+
transportInstance = new TransportNodeHidSingleton(new HID.HID(device.path), {
|
|
91
|
+
context,
|
|
92
|
+
});
|
|
84
93
|
const unlisten = listenDevices(() => { }, () => {
|
|
85
|
-
//
|
|
94
|
+
// Assumes any ledger disconnection concerns current transport
|
|
86
95
|
if (transportInstance) {
|
|
87
96
|
transportInstance.emit("disconnect");
|
|
88
97
|
}
|
|
@@ -90,7 +99,7 @@ class TransportNodeHidSingleton extends TransportNodeHidNoEvents {
|
|
|
90
99
|
const onDisconnect = () => {
|
|
91
100
|
if (!transportInstance)
|
|
92
101
|
return;
|
|
93
|
-
|
|
102
|
+
tracer.trace("Device was disconnected, clearing transport instance ...");
|
|
94
103
|
transportInstance.off("disconnect", onDisconnect);
|
|
95
104
|
transportInstance = null;
|
|
96
105
|
unlisten();
|
|
@@ -104,6 +113,7 @@ class TransportNodeHidSingleton extends TransportNodeHidNoEvents {
|
|
|
104
113
|
}
|
|
105
114
|
/**
|
|
106
115
|
* Exchange with the device using APDU protocol.
|
|
116
|
+
*
|
|
107
117
|
* @param apdu
|
|
108
118
|
* @returns a promise of apdu response
|
|
109
119
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TransportNodeHid.js","sourceRoot":"","sources":["../src/TransportNodeHid.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,GAAG,MAAM,UAAU,CAAC;AAC3B,OAAO,wBAAwB,EAAE,EAAE,UAAU,EAAE,MAAM,0CAA0C,CAAC;AAEhG,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"TransportNodeHid.js","sourceRoot":"","sources":["../src/TransportNodeHid.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"listenDevices.d.ts","sourceRoot":"","sources":["../src/listenDevices.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"listenDevices.d.ts","sourceRoot":"","sources":["../src/listenDevices.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,MAAM,GAAG;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC;AAMF,eAAO,MAAM,cAAc,MAAO,MAAM,SAEvC,CAAC;AAiBF,eAAO,MAAM,aAAa,iBAAkB,MAAM,KAAK,IAAI,mBAAmB,MAAM,KAAK,IAAI,eAqC5F,CAAC"}
|
package/lib-es/listenDevices.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { usb } from "usb";
|
|
2
2
|
import { ledgerUSBVendorId } from "@ledgerhq/devices";
|
|
3
|
-
import {
|
|
3
|
+
import { LocalTracer } from "@ledgerhq/logs";
|
|
4
|
+
const LOG_TYPE = "usb-detection";
|
|
4
5
|
const deviceToLog = ({ deviceDescriptor: { idProduct }, busNumber, deviceAddress }) => `productId=${idProduct} busNumber=${busNumber} deviceAddress=${deviceAddress}`;
|
|
5
6
|
let usbDebounce = 1000;
|
|
6
7
|
export const setUsbDebounce = (n) => {
|
|
@@ -17,11 +18,12 @@ const mapRawDevice = ({ busNumber: locationId, deviceAddress, deviceDescriptor:
|
|
|
17
18
|
});
|
|
18
19
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
19
20
|
export const listenDevices = (onAdd, onRemove) => {
|
|
21
|
+
const tracer = new LocalTracer(LOG_TYPE, { function: "listenDevices " });
|
|
20
22
|
let timeout;
|
|
21
23
|
const add = device => {
|
|
22
24
|
if (device.deviceDescriptor.idVendor !== ledgerUSBVendorId)
|
|
23
25
|
return;
|
|
24
|
-
|
|
26
|
+
tracer.trace(`add: ${deviceToLog(device)}`, { device });
|
|
25
27
|
if (!timeout) {
|
|
26
28
|
// a time is needed for the device to actually be connectable over HID..
|
|
27
29
|
// we also take this time to not emit the device yet and potentially cancel it if a remove happens.
|
|
@@ -34,7 +36,7 @@ export const listenDevices = (onAdd, onRemove) => {
|
|
|
34
36
|
const remove = device => {
|
|
35
37
|
if (device.deviceDescriptor.idVendor !== ledgerUSBVendorId)
|
|
36
38
|
return;
|
|
37
|
-
|
|
39
|
+
tracer.trace(`remove: ${deviceToLog(device)}`, { device });
|
|
38
40
|
if (timeout) {
|
|
39
41
|
clearTimeout(timeout);
|
|
40
42
|
timeout = null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"listenDevices.js","sourceRoot":"","sources":["../src/listenDevices.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAC1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"listenDevices.js","sourceRoot":"","sources":["../src/listenDevices.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAC1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,MAAM,QAAQ,GAAG,eAAe,CAAC;AAYjC,MAAM,WAAW,GAAG,CAAC,EAAE,gBAAgB,EAAE,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,aAAa,EAAE,EAAE,EAAE,CACpF,aAAa,SAAS,cAAc,SAAS,kBAAkB,aAAa,EAAE,CAAC;AAEjF,IAAI,WAAW,GAAG,IAAI,CAAC;AACvB,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAS,EAAE,EAAE;IAC1C,WAAW,GAAG,CAAC,CAAC;AAClB,CAAC,CAAC;AAEF,MAAM,YAAY,GAAG,CAAC,EACpB,SAAS,EAAE,UAAU,EACrB,aAAa,EACb,gBAAgB,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,YAAY,EAAE,GAChF,EAAU,EAAE,CAAC,CAAC;IACzB,UAAU;IACV,QAAQ;IACR,SAAS;IACT,UAAU,EAAE,EAAE;IACd,YAAY,EAAE,EAAE;IAChB,YAAY;IACZ,aAAa;CACd,CAAC,CAAC;AAEH,6EAA6E;AAC7E,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,KAA6B,EAAE,QAAgC,EAAE,EAAE;IAC/F,MAAM,MAAM,GAAG,IAAI,WAAW,CAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAC,CAAC;IACzE,IAAI,OAAO,CAAC;IAEZ,MAAM,GAAG,GAAG,MAAM,CAAC,EAAE;QACnB,IAAI,MAAM,CAAC,gBAAgB,CAAC,QAAQ,KAAK,iBAAiB;YAAE,OAAO;QACnE,MAAM,CAAC,KAAK,CAAC,QAAQ,WAAW,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QAExD,IAAI,CAAC,OAAO,EAAE;YACZ,wEAAwE;YACxE,mGAAmG;YACnG,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;gBACxB,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC;gBAC5B,OAAO,GAAG,IAAI,CAAC;YACjB,CAAC,EAAE,WAAW,CAAC,CAAC;SACjB;IACH,CAAC,CAAC;IAEF,MAAM,MAAM,GAAG,MAAM,CAAC,EAAE;QACtB,IAAI,MAAM,CAAC,gBAAgB,CAAC,QAAQ,KAAK,iBAAiB;YAAE,OAAO;QACnE,MAAM,CAAC,KAAK,CAAC,WAAW,WAAW,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QAE3D,IAAI,OAAO,EAAE;YACX,YAAY,CAAC,OAAO,CAAC,CAAC;YACtB,OAAO,GAAG,IAAI,CAAC;SAChB;aAAM;YACL,QAAQ,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC;SAChC;IACH,CAAC,CAAC;IAEF,GAAG,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IACtB,GAAG,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAEzB,OAAO,GAAG,EAAE;QACV,IAAI,OAAO;YAAE,YAAY,CAAC,OAAO,CAAC,CAAC;QACnC,GAAG,CAAC,kBAAkB,EAAE,CAAC;IAC3B,CAAC,CAAC;AACJ,CAAC,CAAC;AAEF,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE;IACtB,GAAG,CAAC,kBAAkB,EAAE,CAAC;AAC3B,CAAC,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ledgerhq/hw-transport-node-hid-singleton",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.29.0-nightly.0",
|
|
4
4
|
"description": "Ledger Hardware Wallet Node implementation of the communication layer, using node-hid and node-usb",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Ledger",
|
|
@@ -30,11 +30,11 @@
|
|
|
30
30
|
"lodash": "^4.17.21",
|
|
31
31
|
"node-hid": "^2.1.2",
|
|
32
32
|
"usb": "2.9.0",
|
|
33
|
-
"@ledgerhq/devices": "^8.0.
|
|
34
|
-
"@ledgerhq/errors": "^6.14.0
|
|
35
|
-
"@ledgerhq/hw-transport": "^6.
|
|
36
|
-
"@ledgerhq/hw-transport-node-hid-noevents": "^6.
|
|
37
|
-
"@ledgerhq/logs": "^6.
|
|
33
|
+
"@ledgerhq/devices": "^8.0.8-nightly.0",
|
|
34
|
+
"@ledgerhq/errors": "^6.14.0",
|
|
35
|
+
"@ledgerhq/hw-transport": "^6.29.0-nightly.0",
|
|
36
|
+
"@ledgerhq/hw-transport-node-hid-noevents": "^6.28.0-nightly.0",
|
|
37
|
+
"@ledgerhq/logs": "^6.11.0-nightly.0"
|
|
38
38
|
},
|
|
39
39
|
"gitHead": "dd0dea64b58e5a9125c8a422dcffd29e5ef6abec",
|
|
40
40
|
"devDependencies": {
|
package/src/TransportNodeHid.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import HID from "node-hid";
|
|
2
2
|
import TransportNodeHidNoEvents, { getDevices } from "@ledgerhq/hw-transport-node-hid-noevents";
|
|
3
3
|
import type { Observer, DescriptorEvent, Subscription } from "@ledgerhq/hw-transport";
|
|
4
|
-
import { log } from "@ledgerhq/logs";
|
|
4
|
+
import { LocalTracer, TraceContext, log } from "@ledgerhq/logs";
|
|
5
5
|
import { identifyUSBProductId } from "@ledgerhq/devices";
|
|
6
6
|
import { CantOpenDevice } from "@ledgerhq/errors";
|
|
7
7
|
import { listenDevices } from "./listenDevices";
|
|
8
8
|
|
|
9
|
+
const LOG_TYPE = "hid-verbose";
|
|
10
|
+
|
|
9
11
|
let transportInstance;
|
|
10
12
|
|
|
11
13
|
const DISCONNECT_TIMEOUT = 5000;
|
|
@@ -33,9 +35,13 @@ export type ListenDescriptorEvent = DescriptorEvent<any>;
|
|
|
33
35
|
* ...
|
|
34
36
|
* TransportNodeHid.create().then(transport => ...)
|
|
35
37
|
*/
|
|
36
|
-
|
|
37
38
|
export default class TransportNodeHidSingleton extends TransportNodeHidNoEvents {
|
|
38
39
|
preventAutoDisconnect = false;
|
|
40
|
+
|
|
41
|
+
constructor(device: HID.HID, { context }: { context?: TraceContext } = {}) {
|
|
42
|
+
super(device, { context, logType: LOG_TYPE });
|
|
43
|
+
}
|
|
44
|
+
|
|
39
45
|
/**
|
|
40
46
|
*
|
|
41
47
|
*/
|
|
@@ -130,24 +136,39 @@ export default class TransportNodeHidSingleton extends TransportNodeHidNoEvents
|
|
|
130
136
|
}
|
|
131
137
|
|
|
132
138
|
/**
|
|
133
|
-
*
|
|
139
|
+
* Connects to the first Ledger device connected via USB
|
|
140
|
+
*
|
|
141
|
+
* Reusing the same TransportNodeHidSingleton instance until a disconnection happens.
|
|
142
|
+
* Pitfall: this implementation only handles 1 device connected via USB
|
|
143
|
+
*
|
|
144
|
+
* Legacy: `_descriptor` is needed to follow the Transport definition
|
|
134
145
|
*/
|
|
135
|
-
static open(
|
|
146
|
+
static open(
|
|
147
|
+
_descriptor: string,
|
|
148
|
+
_timeoutMs?: number,
|
|
149
|
+
context?: TraceContext,
|
|
150
|
+
): Promise<TransportNodeHidSingleton> {
|
|
151
|
+
const tracer = new LocalTracer(LOG_TYPE, context);
|
|
136
152
|
clearDisconnectTimeout();
|
|
153
|
+
|
|
137
154
|
return Promise.resolve().then(() => {
|
|
138
155
|
if (transportInstance) {
|
|
139
|
-
|
|
156
|
+
tracer.trace("Reusing already opened transport instance");
|
|
140
157
|
return transportInstance;
|
|
141
158
|
}
|
|
142
159
|
|
|
143
160
|
const device = getDevices()[0];
|
|
144
161
|
if (!device) throw new CantOpenDevice("no device found");
|
|
145
|
-
|
|
146
|
-
|
|
162
|
+
|
|
163
|
+
tracer.trace("Found a device, creating HID transport instance ...", { device });
|
|
164
|
+
transportInstance = new TransportNodeHidSingleton(new HID.HID(device.path as string), {
|
|
165
|
+
context,
|
|
166
|
+
});
|
|
167
|
+
|
|
147
168
|
const unlisten = listenDevices(
|
|
148
169
|
() => {},
|
|
149
170
|
() => {
|
|
150
|
-
//
|
|
171
|
+
// Assumes any ledger disconnection concerns current transport
|
|
151
172
|
if (transportInstance) {
|
|
152
173
|
transportInstance.emit("disconnect");
|
|
153
174
|
}
|
|
@@ -156,7 +177,7 @@ export default class TransportNodeHidSingleton extends TransportNodeHidNoEvents
|
|
|
156
177
|
|
|
157
178
|
const onDisconnect = () => {
|
|
158
179
|
if (!transportInstance) return;
|
|
159
|
-
|
|
180
|
+
tracer.trace("Device was disconnected, clearing transport instance ...");
|
|
160
181
|
transportInstance.off("disconnect", onDisconnect);
|
|
161
182
|
transportInstance = null;
|
|
162
183
|
unlisten();
|
|
@@ -173,6 +194,7 @@ export default class TransportNodeHidSingleton extends TransportNodeHidNoEvents
|
|
|
173
194
|
|
|
174
195
|
/**
|
|
175
196
|
* Exchange with the device using APDU protocol.
|
|
197
|
+
*
|
|
176
198
|
* @param apdu
|
|
177
199
|
* @returns a promise of apdu response
|
|
178
200
|
*/
|
package/src/listenDevices.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { usb } from "usb";
|
|
2
2
|
import { ledgerUSBVendorId } from "@ledgerhq/devices";
|
|
3
|
-
import {
|
|
3
|
+
import { LocalTracer } from "@ledgerhq/logs";
|
|
4
|
+
|
|
5
|
+
const LOG_TYPE = "usb-detection";
|
|
4
6
|
|
|
5
7
|
export type Device = {
|
|
6
8
|
locationId: number;
|
|
@@ -36,11 +38,12 @@ const mapRawDevice = ({
|
|
|
36
38
|
|
|
37
39
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
38
40
|
export const listenDevices = (onAdd: (arg0: Device) => void, onRemove: (arg0: Device) => void) => {
|
|
41
|
+
const tracer = new LocalTracer(LOG_TYPE, { function: "listenDevices " });
|
|
39
42
|
let timeout;
|
|
40
43
|
|
|
41
44
|
const add = device => {
|
|
42
45
|
if (device.deviceDescriptor.idVendor !== ledgerUSBVendorId) return;
|
|
43
|
-
|
|
46
|
+
tracer.trace(`add: ${deviceToLog(device)}`, { device });
|
|
44
47
|
|
|
45
48
|
if (!timeout) {
|
|
46
49
|
// a time is needed for the device to actually be connectable over HID..
|
|
@@ -54,7 +57,7 @@ export const listenDevices = (onAdd: (arg0: Device) => void, onRemove: (arg0: De
|
|
|
54
57
|
|
|
55
58
|
const remove = device => {
|
|
56
59
|
if (device.deviceDescriptor.idVendor !== ledgerUSBVendorId) return;
|
|
57
|
-
|
|
60
|
+
tracer.trace(`remove: ${deviceToLog(device)}`, { device });
|
|
58
61
|
|
|
59
62
|
if (timeout) {
|
|
60
63
|
clearTimeout(timeout);
|