@ledgerhq/hw-transport-node-speculos 6.27.13 → 6.27.14-next.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 +8 -0
- package/lib/SpeculosTransport.d.ts +2 -1
- package/lib/SpeculosTransport.d.ts.map +1 -1
- package/lib/SpeculosTransport.js +103 -163
- package/lib/SpeculosTransport.js.map +1 -1
- package/lib-es/SpeculosTransport.d.ts +2 -1
- package/lib-es/SpeculosTransport.d.ts.map +1 -1
- package/lib-es/SpeculosTransport.js +96 -157
- package/lib-es/SpeculosTransport.js.map +1 -1
- package/package.json +5 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# @ledgerhq/hw-transport-node-speculos
|
|
2
2
|
|
|
3
|
+
## 6.27.14-next.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [[`87d2349fd8`](https://github.com/LedgerHQ/ledger-live/commit/87d2349fd835e5deb39d1ee8dfcf3539f4195472)]:
|
|
8
|
+
- @ledgerhq/errors@6.12.5-next.0
|
|
9
|
+
- @ledgerhq/hw-transport@6.28.3-next.0
|
|
10
|
+
|
|
3
11
|
## 6.27.13
|
|
4
12
|
|
|
5
13
|
### Patch Changes
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
2
3
|
import { Subject } from "rxjs";
|
|
3
4
|
import net from "net";
|
|
4
5
|
import Transport from "@ledgerhq/hw-transport";
|
|
5
6
|
/**
|
|
6
7
|
*
|
|
7
8
|
*/
|
|
8
|
-
export
|
|
9
|
+
export type SpeculosTransportOpts = {
|
|
9
10
|
apduPort: number;
|
|
10
11
|
buttonPort?: number;
|
|
11
12
|
automationPort?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SpeculosTransport.d.ts","sourceRoot":"","sources":["../src/SpeculosTransport.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SpeculosTransport.d.ts","sourceRoot":"","sources":["../src/SpeculosTransport.ts"],"names":[],"mappings":";;AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,SAAS,MAAM,wBAAwB,CAAC;AAQ/C;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AACF;;;;;;;GAOG;AAEH,MAAM,CAAC,OAAO,OAAO,iBAAkB,SAAQ,SAAS;IACtD,MAAM,CAAC,WAAW,QAAO,QAAQ,OAAO,CAAC,CAA0B;IAEnE,MAAM,CAAC,IAAI,QAAO,GAAG,CAAwB;IAC7C,MAAM,CAAC,MAAM,cAAe,GAAG;;MAE5B;IAEH;;OAEG;IACH,MAAM,CAAC,IAAI,SAAU,qBAAqB,KAAG,QAAQ,iBAAiB,CAAC,CAgBlE;IACL,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC;IACvB,IAAI,EAAE,qBAAqB,CAAC;IAC5B,cAAc,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,IAAI,CAAc;IACnD,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAc;IACrD,gBAAgB,EAAE,GAAG,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAChD,gBAAgB,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAiB;gBAEnD,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,qBAAqB;IA2C/D;;;;;OAKG;IACH,MAAM,YAAa,MAAM,KAAG,QAAQ,IAAI,CAAC,CAepC;IAEC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAa1C,cAAc;IAER,KAAK;CAKZ"}
|
package/lib/SpeculosTransport.js
CHANGED
|
@@ -1,19 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __extends = (this && this.__extends) || (function () {
|
|
3
|
-
var extendStatics = function (d, b) {
|
|
4
|
-
extendStatics = Object.setPrototypeOf ||
|
|
5
|
-
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
6
|
-
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
7
|
-
return extendStatics(d, b);
|
|
8
|
-
};
|
|
9
|
-
return function (d, b) {
|
|
10
|
-
if (typeof b !== "function" && b !== null)
|
|
11
|
-
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
12
|
-
extendStatics(d, b);
|
|
13
|
-
function __() { this.constructor = d; }
|
|
14
|
-
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
15
|
-
};
|
|
16
|
-
})();
|
|
17
2
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
18
3
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
19
4
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -23,42 +8,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
23
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
24
9
|
});
|
|
25
10
|
};
|
|
26
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
27
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
28
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
29
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
30
|
-
function step(op) {
|
|
31
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
32
|
-
while (_) try {
|
|
33
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
34
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
35
|
-
switch (op[0]) {
|
|
36
|
-
case 0: case 1: t = op; break;
|
|
37
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
38
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
39
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
40
|
-
default:
|
|
41
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
42
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
43
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
44
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
45
|
-
if (t[2]) _.ops.pop();
|
|
46
|
-
_.trys.pop(); continue;
|
|
47
|
-
}
|
|
48
|
-
op = body.call(thisArg, _);
|
|
49
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
50
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
11
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
54
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
55
13
|
};
|
|
56
|
-
exports
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const rxjs_1 = require("rxjs");
|
|
16
|
+
const net_1 = __importDefault(require("net"));
|
|
17
|
+
const hw_transport_1 = __importDefault(require("@ledgerhq/hw-transport"));
|
|
18
|
+
const errors_1 = require("@ledgerhq/errors");
|
|
19
|
+
const logs_1 = require("@ledgerhq/logs");
|
|
62
20
|
/**
|
|
63
21
|
* Speculos TCP transport implementation
|
|
64
22
|
*
|
|
@@ -67,153 +25,135 @@ var logs_1 = require("@ledgerhq/logs");
|
|
|
67
25
|
* const transport = await SpeculosTransport.open({ apduPort });
|
|
68
26
|
* const res = await transport.send(0xE0, 0x01, 0, 0);
|
|
69
27
|
*/
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
_this.automationEvents = new rxjs_1.Subject();
|
|
28
|
+
class SpeculosTransport extends hw_transport_1.default {
|
|
29
|
+
constructor(apduSocket, opts) {
|
|
30
|
+
super();
|
|
31
|
+
this.rejectExchange = (_e) => { };
|
|
32
|
+
this.resolveExchange = (_b) => { };
|
|
33
|
+
this.automationEvents = new rxjs_1.Subject();
|
|
77
34
|
/**
|
|
78
35
|
* Send a speculos button command
|
|
79
36
|
* typically "Ll" would press and release the left button
|
|
80
37
|
* typically "Rr" would press and release the right button
|
|
81
38
|
* @param {*} command
|
|
82
39
|
*/
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
socket.
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
socket.
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
resolve();
|
|
98
|
-
});
|
|
40
|
+
this.button = (command) => new Promise((resolve, reject) => {
|
|
41
|
+
(0, logs_1.log)("speculos-button", command);
|
|
42
|
+
const { buttonPort, host } = this.opts;
|
|
43
|
+
if (!buttonPort)
|
|
44
|
+
throw new Error("buttonPort is missing");
|
|
45
|
+
const socket = new net_1.default.Socket();
|
|
46
|
+
socket.on("error", (e) => {
|
|
47
|
+
socket.destroy();
|
|
48
|
+
reject(e);
|
|
49
|
+
});
|
|
50
|
+
socket.connect(buttonPort, host || "127.0.0.1", () => {
|
|
51
|
+
socket.write(Buffer.from(command, "ascii"));
|
|
52
|
+
socket.destroy();
|
|
53
|
+
resolve();
|
|
99
54
|
});
|
|
100
|
-
};
|
|
101
|
-
_this.opts = opts;
|
|
102
|
-
_this.apduSocket = apduSocket;
|
|
103
|
-
apduSocket.on("error", function (e) {
|
|
104
|
-
_this.emit("disconnect", new errors_1.DisconnectedDevice(e.message));
|
|
105
|
-
_this.rejectExchange(e);
|
|
106
|
-
_this.apduSocket.destroy();
|
|
107
55
|
});
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
56
|
+
this.opts = opts;
|
|
57
|
+
this.apduSocket = apduSocket;
|
|
58
|
+
apduSocket.on("error", (e) => {
|
|
59
|
+
this.emit("disconnect", new errors_1.DisconnectedDevice(e.message));
|
|
60
|
+
this.rejectExchange(e);
|
|
61
|
+
this.apduSocket.destroy();
|
|
111
62
|
});
|
|
112
|
-
apduSocket.on("
|
|
63
|
+
apduSocket.on("end", () => {
|
|
64
|
+
this.emit("disconnect", new errors_1.DisconnectedDevice());
|
|
65
|
+
this.rejectExchange(new errors_1.DisconnectedDeviceDuringOperation());
|
|
66
|
+
});
|
|
67
|
+
apduSocket.on("data", (data) => {
|
|
113
68
|
try {
|
|
114
|
-
|
|
69
|
+
this.resolveExchange(decodeAPDUPayload(data));
|
|
115
70
|
}
|
|
116
71
|
catch (e) {
|
|
117
|
-
|
|
72
|
+
this.rejectExchange(e);
|
|
118
73
|
}
|
|
119
74
|
});
|
|
120
|
-
|
|
75
|
+
const { automationPort } = opts;
|
|
121
76
|
if (automationPort) {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
77
|
+
const socket = new net_1.default.Socket();
|
|
78
|
+
this.automationSocket = socket;
|
|
79
|
+
socket.on("error", (e) => {
|
|
125
80
|
(0, logs_1.log)("speculos-automation-error", String(e));
|
|
126
|
-
|
|
81
|
+
socket.destroy();
|
|
127
82
|
});
|
|
128
|
-
|
|
83
|
+
socket.on("data", (data) => {
|
|
129
84
|
(0, logs_1.log)("speculos-automation-data", data.toString("ascii"));
|
|
130
|
-
|
|
85
|
+
const split = data.toString("ascii").split("\n");
|
|
131
86
|
split
|
|
132
|
-
.filter(
|
|
133
|
-
.forEach(
|
|
134
|
-
|
|
135
|
-
|
|
87
|
+
.filter((ascii) => !!ascii)
|
|
88
|
+
.forEach((ascii) => {
|
|
89
|
+
const json = JSON.parse(ascii);
|
|
90
|
+
this.automationEvents.next(json);
|
|
136
91
|
});
|
|
137
92
|
});
|
|
138
|
-
|
|
93
|
+
socket.connect(automationPort, opts.host || "127.0.0.1");
|
|
139
94
|
}
|
|
140
|
-
return _this;
|
|
141
95
|
}
|
|
142
|
-
|
|
143
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
encoded = encodeAPDU(apdu);
|
|
152
|
-
return [4 /*yield*/, new Promise(function (resolve, reject) {
|
|
153
|
-
_this.rejectExchange = reject;
|
|
154
|
-
_this.resolveExchange = resolve;
|
|
155
|
-
_this.apduSocket.write(encoded);
|
|
156
|
-
})];
|
|
157
|
-
case 1:
|
|
158
|
-
res = _a.sent();
|
|
159
|
-
(0, logs_1.log)("apdu", "<= " + res.toString("hex"));
|
|
160
|
-
return [2 /*return*/, res];
|
|
161
|
-
}
|
|
96
|
+
exchange(apdu) {
|
|
97
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
98
|
+
const hex = apdu.toString("hex");
|
|
99
|
+
(0, logs_1.log)("apdu", "=> " + hex);
|
|
100
|
+
const encoded = encodeAPDU(apdu);
|
|
101
|
+
const res = yield new Promise((resolve, reject) => {
|
|
102
|
+
this.rejectExchange = reject;
|
|
103
|
+
this.resolveExchange = resolve;
|
|
104
|
+
this.apduSocket.write(encoded);
|
|
162
105
|
});
|
|
106
|
+
(0, logs_1.log)("apdu", "<= " + res.toString("hex"));
|
|
107
|
+
return res;
|
|
163
108
|
});
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
return [2 /*return*/, Promise.resolve()];
|
|
173
|
-
});
|
|
174
|
-
});
|
|
175
|
-
};
|
|
176
|
-
SpeculosTransport.isSupported = function () { return Promise.resolve(true); };
|
|
177
|
-
// this transport is not discoverable
|
|
178
|
-
SpeculosTransport.list = function () { return Promise.resolve([]); };
|
|
179
|
-
SpeculosTransport.listen = function (_observer) { return ({
|
|
180
|
-
unsubscribe: function () { }
|
|
181
|
-
}); };
|
|
182
|
-
/**
|
|
183
|
-
*
|
|
184
|
-
*/
|
|
185
|
-
SpeculosTransport.open = function (opts) {
|
|
186
|
-
return new Promise(function (resolve, reject) {
|
|
187
|
-
var socket = new net_1["default"].Socket();
|
|
188
|
-
socket.on("error", function (e) {
|
|
189
|
-
socket.destroy();
|
|
190
|
-
reject(e);
|
|
191
|
-
});
|
|
192
|
-
socket.on("end", function () {
|
|
193
|
-
reject(new errors_1.DisconnectedDevice("tcp closed"));
|
|
194
|
-
});
|
|
195
|
-
socket.connect(opts.apduPort, opts.host || "127.0.0.1", function () {
|
|
196
|
-
// we delay a bit the transport creation to make sure the tcp does not hang up
|
|
197
|
-
setTimeout(function () {
|
|
198
|
-
resolve(new SpeculosTransport(socket, opts));
|
|
199
|
-
}, 100);
|
|
200
|
-
});
|
|
109
|
+
}
|
|
110
|
+
setScrambleKey() { }
|
|
111
|
+
close() {
|
|
112
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
113
|
+
if (this.automationSocket)
|
|
114
|
+
this.automationSocket.destroy();
|
|
115
|
+
this.apduSocket.destroy();
|
|
116
|
+
return Promise.resolve();
|
|
201
117
|
});
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
exports.default = SpeculosTransport;
|
|
121
|
+
SpeculosTransport.isSupported = () => Promise.resolve(true);
|
|
122
|
+
// this transport is not discoverable
|
|
123
|
+
SpeculosTransport.list = () => Promise.resolve([]);
|
|
124
|
+
SpeculosTransport.listen = (_observer) => ({
|
|
125
|
+
unsubscribe: () => { },
|
|
126
|
+
});
|
|
127
|
+
/**
|
|
128
|
+
*
|
|
129
|
+
*/
|
|
130
|
+
SpeculosTransport.open = (opts) => new Promise((resolve, reject) => {
|
|
131
|
+
const socket = new net_1.default.Socket();
|
|
132
|
+
socket.on("error", (e) => {
|
|
133
|
+
socket.destroy();
|
|
134
|
+
reject(e);
|
|
135
|
+
});
|
|
136
|
+
socket.on("end", () => {
|
|
137
|
+
reject(new errors_1.DisconnectedDevice("tcp closed"));
|
|
138
|
+
});
|
|
139
|
+
socket.connect(opts.apduPort, opts.host || "127.0.0.1", () => {
|
|
140
|
+
// we delay a bit the transport creation to make sure the tcp does not hang up
|
|
141
|
+
setTimeout(() => {
|
|
142
|
+
resolve(new SpeculosTransport(socket, opts));
|
|
143
|
+
}, 100);
|
|
144
|
+
});
|
|
145
|
+
});
|
|
206
146
|
function encodeAPDU(apdu) {
|
|
207
|
-
|
|
147
|
+
const size = Buffer.allocUnsafe(4);
|
|
208
148
|
size.writeUIntBE(apdu.length, 0, 4);
|
|
209
149
|
return Buffer.concat([size, apdu]);
|
|
210
150
|
}
|
|
211
151
|
function decodeAPDUPayload(data) {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
152
|
+
const dataLength = data.readUIntBE(0, 4); // 4 bytes tells the data length
|
|
153
|
+
const size = dataLength + 2; // size does not include the status code so we add 2
|
|
154
|
+
const payload = data.slice(4);
|
|
215
155
|
if (payload.length !== size) {
|
|
216
|
-
throw new errors_1.TransportError(
|
|
156
|
+
throw new errors_1.TransportError(`Expected payload of length ${size} but got ${payload.length}`, "");
|
|
217
157
|
}
|
|
218
158
|
return payload;
|
|
219
159
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SpeculosTransport.js","sourceRoot":"","sources":["../src/SpeculosTransport.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SpeculosTransport.js","sourceRoot":"","sources":["../src/SpeculosTransport.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
2
3
|
import { Subject } from "rxjs";
|
|
3
4
|
import net from "net";
|
|
4
5
|
import Transport from "@ledgerhq/hw-transport";
|
|
5
6
|
/**
|
|
6
7
|
*
|
|
7
8
|
*/
|
|
8
|
-
export
|
|
9
|
+
export type SpeculosTransportOpts = {
|
|
9
10
|
apduPort: number;
|
|
10
11
|
buttonPort?: number;
|
|
11
12
|
automationPort?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SpeculosTransport.d.ts","sourceRoot":"","sources":["../src/SpeculosTransport.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SpeculosTransport.d.ts","sourceRoot":"","sources":["../src/SpeculosTransport.ts"],"names":[],"mappings":";;AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAC/B,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,SAAS,MAAM,wBAAwB,CAAC;AAQ/C;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AACF;;;;;;;GAOG;AAEH,MAAM,CAAC,OAAO,OAAO,iBAAkB,SAAQ,SAAS;IACtD,MAAM,CAAC,WAAW,QAAO,QAAQ,OAAO,CAAC,CAA0B;IAEnE,MAAM,CAAC,IAAI,QAAO,GAAG,CAAwB;IAC7C,MAAM,CAAC,MAAM,cAAe,GAAG;;MAE5B;IAEH;;OAEG;IACH,MAAM,CAAC,IAAI,SAAU,qBAAqB,KAAG,QAAQ,iBAAiB,CAAC,CAgBlE;IACL,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC;IACvB,IAAI,EAAE,qBAAqB,CAAC;IAC5B,cAAc,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,IAAI,CAAc;IACnD,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAc;IACrD,gBAAgB,EAAE,GAAG,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAChD,gBAAgB,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAiB;gBAEnD,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,qBAAqB;IA2C/D;;;;;OAKG;IACH,MAAM,YAAa,MAAM,KAAG,QAAQ,IAAI,CAAC,CAepC;IAEC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAa1C,cAAc;IAER,KAAK;CAKZ"}
|
|
@@ -1,18 +1,3 @@
|
|
|
1
|
-
var __extends = (this && this.__extends) || (function () {
|
|
2
|
-
var extendStatics = function (d, b) {
|
|
3
|
-
extendStatics = Object.setPrototypeOf ||
|
|
4
|
-
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
5
|
-
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
6
|
-
return extendStatics(d, b);
|
|
7
|
-
};
|
|
8
|
-
return function (d, b) {
|
|
9
|
-
if (typeof b !== "function" && b !== null)
|
|
10
|
-
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
11
|
-
extendStatics(d, b);
|
|
12
|
-
function __() { this.constructor = d; }
|
|
13
|
-
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
14
|
-
};
|
|
15
|
-
})();
|
|
16
1
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
17
2
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
18
3
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -22,33 +7,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
22
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
23
8
|
});
|
|
24
9
|
};
|
|
25
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
26
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
27
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
28
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
29
|
-
function step(op) {
|
|
30
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
31
|
-
while (_) try {
|
|
32
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
33
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
34
|
-
switch (op[0]) {
|
|
35
|
-
case 0: case 1: t = op; break;
|
|
36
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
37
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
38
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
39
|
-
default:
|
|
40
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
41
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
42
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
43
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
44
|
-
if (t[2]) _.ops.pop();
|
|
45
|
-
_.trys.pop(); continue;
|
|
46
|
-
}
|
|
47
|
-
op = body.call(thisArg, _);
|
|
48
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
49
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
10
|
import { Subject } from "rxjs";
|
|
53
11
|
import net from "net";
|
|
54
12
|
import Transport from "@ledgerhq/hw-transport";
|
|
@@ -62,153 +20,134 @@ import { log } from "@ledgerhq/logs";
|
|
|
62
20
|
* const transport = await SpeculosTransport.open({ apduPort });
|
|
63
21
|
* const res = await transport.send(0xE0, 0x01, 0, 0);
|
|
64
22
|
*/
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
_this.automationEvents = new Subject();
|
|
23
|
+
export default class SpeculosTransport extends Transport {
|
|
24
|
+
constructor(apduSocket, opts) {
|
|
25
|
+
super();
|
|
26
|
+
this.rejectExchange = (_e) => { };
|
|
27
|
+
this.resolveExchange = (_b) => { };
|
|
28
|
+
this.automationEvents = new Subject();
|
|
72
29
|
/**
|
|
73
30
|
* Send a speculos button command
|
|
74
31
|
* typically "Ll" would press and release the left button
|
|
75
32
|
* typically "Rr" would press and release the right button
|
|
76
33
|
* @param {*} command
|
|
77
34
|
*/
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
socket.
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
socket.
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
resolve();
|
|
93
|
-
});
|
|
35
|
+
this.button = (command) => new Promise((resolve, reject) => {
|
|
36
|
+
log("speculos-button", command);
|
|
37
|
+
const { buttonPort, host } = this.opts;
|
|
38
|
+
if (!buttonPort)
|
|
39
|
+
throw new Error("buttonPort is missing");
|
|
40
|
+
const socket = new net.Socket();
|
|
41
|
+
socket.on("error", (e) => {
|
|
42
|
+
socket.destroy();
|
|
43
|
+
reject(e);
|
|
44
|
+
});
|
|
45
|
+
socket.connect(buttonPort, host || "127.0.0.1", () => {
|
|
46
|
+
socket.write(Buffer.from(command, "ascii"));
|
|
47
|
+
socket.destroy();
|
|
48
|
+
resolve();
|
|
94
49
|
});
|
|
95
|
-
};
|
|
96
|
-
_this.opts = opts;
|
|
97
|
-
_this.apduSocket = apduSocket;
|
|
98
|
-
apduSocket.on("error", function (e) {
|
|
99
|
-
_this.emit("disconnect", new DisconnectedDevice(e.message));
|
|
100
|
-
_this.rejectExchange(e);
|
|
101
|
-
_this.apduSocket.destroy();
|
|
102
50
|
});
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
51
|
+
this.opts = opts;
|
|
52
|
+
this.apduSocket = apduSocket;
|
|
53
|
+
apduSocket.on("error", (e) => {
|
|
54
|
+
this.emit("disconnect", new DisconnectedDevice(e.message));
|
|
55
|
+
this.rejectExchange(e);
|
|
56
|
+
this.apduSocket.destroy();
|
|
106
57
|
});
|
|
107
|
-
apduSocket.on("
|
|
58
|
+
apduSocket.on("end", () => {
|
|
59
|
+
this.emit("disconnect", new DisconnectedDevice());
|
|
60
|
+
this.rejectExchange(new DisconnectedDeviceDuringOperation());
|
|
61
|
+
});
|
|
62
|
+
apduSocket.on("data", (data) => {
|
|
108
63
|
try {
|
|
109
|
-
|
|
64
|
+
this.resolveExchange(decodeAPDUPayload(data));
|
|
110
65
|
}
|
|
111
66
|
catch (e) {
|
|
112
|
-
|
|
67
|
+
this.rejectExchange(e);
|
|
113
68
|
}
|
|
114
69
|
});
|
|
115
|
-
|
|
70
|
+
const { automationPort } = opts;
|
|
116
71
|
if (automationPort) {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
72
|
+
const socket = new net.Socket();
|
|
73
|
+
this.automationSocket = socket;
|
|
74
|
+
socket.on("error", (e) => {
|
|
120
75
|
log("speculos-automation-error", String(e));
|
|
121
|
-
|
|
76
|
+
socket.destroy();
|
|
122
77
|
});
|
|
123
|
-
|
|
78
|
+
socket.on("data", (data) => {
|
|
124
79
|
log("speculos-automation-data", data.toString("ascii"));
|
|
125
|
-
|
|
80
|
+
const split = data.toString("ascii").split("\n");
|
|
126
81
|
split
|
|
127
|
-
.filter(
|
|
128
|
-
.forEach(
|
|
129
|
-
|
|
130
|
-
|
|
82
|
+
.filter((ascii) => !!ascii)
|
|
83
|
+
.forEach((ascii) => {
|
|
84
|
+
const json = JSON.parse(ascii);
|
|
85
|
+
this.automationEvents.next(json);
|
|
131
86
|
});
|
|
132
87
|
});
|
|
133
|
-
|
|
88
|
+
socket.connect(automationPort, opts.host || "127.0.0.1");
|
|
134
89
|
}
|
|
135
|
-
return _this;
|
|
136
90
|
}
|
|
137
|
-
|
|
138
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
encoded = encodeAPDU(apdu);
|
|
147
|
-
return [4 /*yield*/, new Promise(function (resolve, reject) {
|
|
148
|
-
_this.rejectExchange = reject;
|
|
149
|
-
_this.resolveExchange = resolve;
|
|
150
|
-
_this.apduSocket.write(encoded);
|
|
151
|
-
})];
|
|
152
|
-
case 1:
|
|
153
|
-
res = _a.sent();
|
|
154
|
-
log("apdu", "<= " + res.toString("hex"));
|
|
155
|
-
return [2 /*return*/, res];
|
|
156
|
-
}
|
|
91
|
+
exchange(apdu) {
|
|
92
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
93
|
+
const hex = apdu.toString("hex");
|
|
94
|
+
log("apdu", "=> " + hex);
|
|
95
|
+
const encoded = encodeAPDU(apdu);
|
|
96
|
+
const res = yield new Promise((resolve, reject) => {
|
|
97
|
+
this.rejectExchange = reject;
|
|
98
|
+
this.resolveExchange = resolve;
|
|
99
|
+
this.apduSocket.write(encoded);
|
|
157
100
|
});
|
|
101
|
+
log("apdu", "<= " + res.toString("hex"));
|
|
102
|
+
return res;
|
|
158
103
|
});
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
return [2 /*return*/, Promise.resolve()];
|
|
168
|
-
});
|
|
169
|
-
});
|
|
170
|
-
};
|
|
171
|
-
SpeculosTransport.isSupported = function () { return Promise.resolve(true); };
|
|
172
|
-
// this transport is not discoverable
|
|
173
|
-
SpeculosTransport.list = function () { return Promise.resolve([]); };
|
|
174
|
-
SpeculosTransport.listen = function (_observer) { return ({
|
|
175
|
-
unsubscribe: function () { }
|
|
176
|
-
}); };
|
|
177
|
-
/**
|
|
178
|
-
*
|
|
179
|
-
*/
|
|
180
|
-
SpeculosTransport.open = function (opts) {
|
|
181
|
-
return new Promise(function (resolve, reject) {
|
|
182
|
-
var socket = new net.Socket();
|
|
183
|
-
socket.on("error", function (e) {
|
|
184
|
-
socket.destroy();
|
|
185
|
-
reject(e);
|
|
186
|
-
});
|
|
187
|
-
socket.on("end", function () {
|
|
188
|
-
reject(new DisconnectedDevice("tcp closed"));
|
|
189
|
-
});
|
|
190
|
-
socket.connect(opts.apduPort, opts.host || "127.0.0.1", function () {
|
|
191
|
-
// we delay a bit the transport creation to make sure the tcp does not hang up
|
|
192
|
-
setTimeout(function () {
|
|
193
|
-
resolve(new SpeculosTransport(socket, opts));
|
|
194
|
-
}, 100);
|
|
195
|
-
});
|
|
104
|
+
}
|
|
105
|
+
setScrambleKey() { }
|
|
106
|
+
close() {
|
|
107
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
108
|
+
if (this.automationSocket)
|
|
109
|
+
this.automationSocket.destroy();
|
|
110
|
+
this.apduSocket.destroy();
|
|
111
|
+
return Promise.resolve();
|
|
196
112
|
});
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
SpeculosTransport.isSupported = () => Promise.resolve(true);
|
|
116
|
+
// this transport is not discoverable
|
|
117
|
+
SpeculosTransport.list = () => Promise.resolve([]);
|
|
118
|
+
SpeculosTransport.listen = (_observer) => ({
|
|
119
|
+
unsubscribe: () => { },
|
|
120
|
+
});
|
|
121
|
+
/**
|
|
122
|
+
*
|
|
123
|
+
*/
|
|
124
|
+
SpeculosTransport.open = (opts) => new Promise((resolve, reject) => {
|
|
125
|
+
const socket = new net.Socket();
|
|
126
|
+
socket.on("error", (e) => {
|
|
127
|
+
socket.destroy();
|
|
128
|
+
reject(e);
|
|
129
|
+
});
|
|
130
|
+
socket.on("end", () => {
|
|
131
|
+
reject(new DisconnectedDevice("tcp closed"));
|
|
132
|
+
});
|
|
133
|
+
socket.connect(opts.apduPort, opts.host || "127.0.0.1", () => {
|
|
134
|
+
// we delay a bit the transport creation to make sure the tcp does not hang up
|
|
135
|
+
setTimeout(() => {
|
|
136
|
+
resolve(new SpeculosTransport(socket, opts));
|
|
137
|
+
}, 100);
|
|
138
|
+
});
|
|
139
|
+
});
|
|
201
140
|
function encodeAPDU(apdu) {
|
|
202
|
-
|
|
141
|
+
const size = Buffer.allocUnsafe(4);
|
|
203
142
|
size.writeUIntBE(apdu.length, 0, 4);
|
|
204
143
|
return Buffer.concat([size, apdu]);
|
|
205
144
|
}
|
|
206
145
|
function decodeAPDUPayload(data) {
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
146
|
+
const dataLength = data.readUIntBE(0, 4); // 4 bytes tells the data length
|
|
147
|
+
const size = dataLength + 2; // size does not include the status code so we add 2
|
|
148
|
+
const payload = data.slice(4);
|
|
210
149
|
if (payload.length !== size) {
|
|
211
|
-
throw new TransportError(
|
|
150
|
+
throw new TransportError(`Expected payload of length ${size} but got ${payload.length}`, "");
|
|
212
151
|
}
|
|
213
152
|
return payload;
|
|
214
153
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SpeculosTransport.js","sourceRoot":"","sources":["../src/SpeculosTransport.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SpeculosTransport.js","sourceRoot":"","sources":["../src/SpeculosTransport.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ledgerhq/hw-transport-node-speculos",
|
|
3
|
-
"version": "6.27.
|
|
3
|
+
"version": "6.27.14-next.0",
|
|
4
4
|
"description": "Ledger Hardware Wallet communication layer with speculos Nano simulator",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Ledger",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"license": "Apache-2.0",
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"rxjs": "6",
|
|
32
|
-
"@ledgerhq/errors": "^6.12.
|
|
33
|
-
"@ledgerhq/hw-transport": "^6.28.
|
|
32
|
+
"@ledgerhq/errors": "^6.12.5-next.0",
|
|
33
|
+
"@ledgerhq/hw-transport": "^6.28.3-next.0",
|
|
34
34
|
"@ledgerhq/logs": "^6.10.1"
|
|
35
35
|
},
|
|
36
36
|
"gitHead": "dd0dea64b58e5a9125c8a422dcffd29e5ef6abec",
|
|
@@ -39,11 +39,10 @@
|
|
|
39
39
|
"@types/node": "^18.15.3",
|
|
40
40
|
"documentation": "13.2.4",
|
|
41
41
|
"jest": "^28.1.1",
|
|
42
|
-
"rimraf": "^4.1
|
|
42
|
+
"rimraf": "^4.4.1",
|
|
43
43
|
"source-map-support": "^0.5.21",
|
|
44
44
|
"ts-jest": "^28.0.5",
|
|
45
|
-
"ts-node": "^10.4.0"
|
|
46
|
-
"typescript": "^4"
|
|
45
|
+
"ts-node": "^10.4.0"
|
|
47
46
|
},
|
|
48
47
|
"scripts": {
|
|
49
48
|
"clean": "rimraf lib lib-es",
|