@ledgerhq/hw-transport-mocker 6.11.2 → 6.25.1-alpha.3
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/lib/RecordStore.js +3 -3
- package/lib/RecordStore.js.map +1 -1
- package/lib-es/RecordStore.js +3 -3
- package/lib-es/RecordStore.js.flow +191 -0
- package/lib-es/RecordStore.js.map +1 -1
- package/lib-es/createTransportRecorder.js.flow +41 -0
- package/lib-es/createTransportReplayer.js.flow +52 -0
- package/lib-es/index.js.flow +6 -0
- package/package.json +3 -3
package/lib/RecordStore.js
CHANGED
|
@@ -53,7 +53,7 @@ RecordStoreQueueEmpty.prototype = new Error();
|
|
|
53
53
|
*/
|
|
54
54
|
function RecordStoreWrongAPDU(expected, got, line) {
|
|
55
55
|
this.name = "RecordStoreWrongAPDU";
|
|
56
|
-
this.message = "wrong apdu to replay line "
|
|
56
|
+
this.message = "wrong apdu to replay line ".concat(line, ". Expected ").concat(expected, ", Got ").concat(got);
|
|
57
57
|
this.expectedAPDU = expected;
|
|
58
58
|
this.gotAPDU = got;
|
|
59
59
|
this.stack = new Error().stack;
|
|
@@ -65,7 +65,7 @@ RecordStoreWrongAPDU.prototype = new Error();
|
|
|
65
65
|
*/
|
|
66
66
|
function RecordStoreRemainingAPDU(expected) {
|
|
67
67
|
this.name = "RecordStoreRemainingAPDU";
|
|
68
|
-
this.message = "replay expected more APDUs to come:\n"
|
|
68
|
+
this.message = "replay expected more APDUs to come:\n".concat(expected);
|
|
69
69
|
this.stack = new Error().stack;
|
|
70
70
|
}
|
|
71
71
|
exports.RecordStoreRemainingAPDU = RecordStoreRemainingAPDU;
|
|
@@ -144,7 +144,7 @@ var RecordStore = /** @class */ (function () {
|
|
|
144
144
|
return (this.queue
|
|
145
145
|
.map(function (_a) {
|
|
146
146
|
var _b = __read(_a, 2), send = _b[0], receive = _b[1];
|
|
147
|
-
return "=> "
|
|
147
|
+
return "=> ".concat(send, "\n<= ").concat(receive);
|
|
148
148
|
})
|
|
149
149
|
.join("\n") + "\n");
|
|
150
150
|
};
|
package/lib/RecordStore.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RecordStore.js","sourceRoot":"","sources":["../src/RecordStore.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;GAEG;AACH,SAAgB,yBAAyB,CAAC,OAAe;IACvD,IAAI,CAAC,IAAI,GAAG,2BAA2B,CAAC;IACxC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACvB,IAAI,CAAC,KAAK,GAAG,IAAI,KAAK,EAAE,CAAC,KAAK,CAAC;AACjC,CAAC;AAJD,8DAIC;AAED,yBAAyB,CAAC,SAAS,GAAG,IAAI,KAAK,EAAE,CAAC;AAElD;;GAEG;AACH,SAAgB,qBAAqB;IACnC,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACpC,IAAI,CAAC,OAAO,GAAG,6BAA6B,CAAC;IAC7C,IAAI,CAAC,KAAK,GAAG,IAAI,KAAK,EAAE,CAAC,KAAK,CAAC;AACjC,CAAC;AAJD,sDAIC;AAED,qBAAqB,CAAC,SAAS,GAAG,IAAI,KAAK,EAAE,CAAC;AAE9C;;GAEG;AACH,SAAgB,oBAAoB,CAClC,QAAgB,EAChB,GAAW,EACX,IAAY;IAEZ,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACnC,IAAI,CAAC,OAAO,GAAG
|
|
1
|
+
{"version":3,"file":"RecordStore.js","sourceRoot":"","sources":["../src/RecordStore.ts"],"names":[],"mappings":"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"}
|
package/lib-es/RecordStore.js
CHANGED
|
@@ -48,7 +48,7 @@ RecordStoreQueueEmpty.prototype = new Error();
|
|
|
48
48
|
*/
|
|
49
49
|
export function RecordStoreWrongAPDU(expected, got, line) {
|
|
50
50
|
this.name = "RecordStoreWrongAPDU";
|
|
51
|
-
this.message = "wrong apdu to replay line "
|
|
51
|
+
this.message = "wrong apdu to replay line ".concat(line, ". Expected ").concat(expected, ", Got ").concat(got);
|
|
52
52
|
this.expectedAPDU = expected;
|
|
53
53
|
this.gotAPDU = got;
|
|
54
54
|
this.stack = new Error().stack;
|
|
@@ -59,7 +59,7 @@ RecordStoreWrongAPDU.prototype = new Error();
|
|
|
59
59
|
*/
|
|
60
60
|
export function RecordStoreRemainingAPDU(expected) {
|
|
61
61
|
this.name = "RecordStoreRemainingAPDU";
|
|
62
|
-
this.message = "replay expected more APDUs to come:\n"
|
|
62
|
+
this.message = "replay expected more APDUs to come:\n".concat(expected);
|
|
63
63
|
this.stack = new Error().stack;
|
|
64
64
|
}
|
|
65
65
|
RecordStoreRemainingAPDU.prototype = new Error();
|
|
@@ -137,7 +137,7 @@ var RecordStore = /** @class */ (function () {
|
|
|
137
137
|
return (this.queue
|
|
138
138
|
.map(function (_a) {
|
|
139
139
|
var _b = __read(_a, 2), send = _b[0], receive = _b[1];
|
|
140
|
-
return "=> "
|
|
140
|
+
return "=> ".concat(send, "\n<= ").concat(receive);
|
|
141
141
|
})
|
|
142
142
|
.join("\n") + "\n");
|
|
143
143
|
};
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
//@flow
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* thrown by the RecordStore.fromString parser.
|
|
5
|
+
*/
|
|
6
|
+
export function RecordStoreInvalidSynthax(message: string) {
|
|
7
|
+
this.name = "RecordStoreInvalidSynthax";
|
|
8
|
+
this.message = message;
|
|
9
|
+
this.stack = new Error().stack;
|
|
10
|
+
}
|
|
11
|
+
//$FlowFixMe
|
|
12
|
+
RecordStoreInvalidSynthax.prototype = new Error();
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* thrown by the replayer if the queue is empty
|
|
16
|
+
*/
|
|
17
|
+
export function RecordStoreQueueEmpty() {
|
|
18
|
+
this.name = "RecordStoreQueueEmpty";
|
|
19
|
+
this.message = "EOF: no more APDU to replay";
|
|
20
|
+
this.stack = new Error().stack;
|
|
21
|
+
}
|
|
22
|
+
//$FlowFixMe
|
|
23
|
+
RecordStoreQueueEmpty.prototype = new Error();
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* thrown by replayer if it meets an unexpected apdu
|
|
27
|
+
*/
|
|
28
|
+
export function RecordStoreWrongAPDU(
|
|
29
|
+
expected: string,
|
|
30
|
+
got: string,
|
|
31
|
+
line: number
|
|
32
|
+
) {
|
|
33
|
+
this.name = "RecordStoreWrongAPDU";
|
|
34
|
+
this.message = `wrong apdu to replay line ${line}. Expected ${expected}, Got ${got}`;
|
|
35
|
+
this.expectedAPDU = expected;
|
|
36
|
+
this.gotAPDU = got;
|
|
37
|
+
this.stack = new Error().stack;
|
|
38
|
+
}
|
|
39
|
+
//$FlowFixMe
|
|
40
|
+
RecordStoreWrongAPDU.prototype = new Error();
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* thrown by ensureQueueEmpty
|
|
44
|
+
*/
|
|
45
|
+
export function RecordStoreRemainingAPDU(expected: string) {
|
|
46
|
+
this.name = "RecordStoreRemainingAPDU";
|
|
47
|
+
this.message = `replay expected more APDUs to come:\n${expected}`;
|
|
48
|
+
this.stack = new Error().stack;
|
|
49
|
+
}
|
|
50
|
+
//$FlowFixMe
|
|
51
|
+
RecordStoreRemainingAPDU.prototype = new Error();
|
|
52
|
+
|
|
53
|
+
export type Queue = [string, string][];
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* - autoSkipUnknownApdu:
|
|
57
|
+
* smart mechanism that would skip an apdu un-recognize to the next one that does
|
|
58
|
+
* this is meant to be used when you have refactored/dropped some APDUs
|
|
59
|
+
* it will produces warnings for you to fix the APDUs queue
|
|
60
|
+
* - warning:
|
|
61
|
+
* allows to override the warning function (defaults to console.warn)
|
|
62
|
+
*/
|
|
63
|
+
export type RecordStoreOptions = {
|
|
64
|
+
autoSkipUnknownApdu: boolean,
|
|
65
|
+
warning: (string) => void,
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const defaultOpts: RecordStoreOptions = {
|
|
69
|
+
autoSkipUnknownApdu: false,
|
|
70
|
+
warning: (log) => console.warn(log),
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* a RecordStore is a stateful object that represents a queue of APDUs.
|
|
75
|
+
* It is both used by replayer and recorder transports and is the basic for writing Ledger tests with a mock device.
|
|
76
|
+
*/
|
|
77
|
+
export class RecordStore {
|
|
78
|
+
passed = 0;
|
|
79
|
+
queue: Queue;
|
|
80
|
+
opts: RecordStoreOptions;
|
|
81
|
+
|
|
82
|
+
constructor(queue?: ?Queue, opts?: $Shape<RecordStoreOptions>) {
|
|
83
|
+
this.queue = queue || [];
|
|
84
|
+
this.opts = { ...defaultOpts, ...opts };
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* check if there is no more APDUs to replay
|
|
89
|
+
*/
|
|
90
|
+
isEmpty = () => this.queue.length === 0;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Record an APDU (used by createTransportRecorder)
|
|
94
|
+
* @param {Buffer} apdu input
|
|
95
|
+
* @param {Buffer} out response
|
|
96
|
+
*/
|
|
97
|
+
recordExchange(apdu: Buffer, out: Buffer) {
|
|
98
|
+
this.queue.push([apdu.toString("hex"), out.toString("hex")]);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Replay an APDU (used by createTransportReplayer)
|
|
103
|
+
* @param apdu
|
|
104
|
+
*/
|
|
105
|
+
replayExchange(apdu: Buffer): Buffer {
|
|
106
|
+
const { queue, opts } = this;
|
|
107
|
+
const apduHex = apdu.toString("hex");
|
|
108
|
+
for (let i = 0; i < queue.length; i++) {
|
|
109
|
+
const head = queue[i];
|
|
110
|
+
const line = 2 * (this.passed + i);
|
|
111
|
+
if (apduHex === head[0]) {
|
|
112
|
+
++this.passed;
|
|
113
|
+
this.queue = queue.slice(i + 1);
|
|
114
|
+
return Buffer.from(head[1], "hex");
|
|
115
|
+
} else {
|
|
116
|
+
if (opts.autoSkipUnknownApdu) {
|
|
117
|
+
opts.warning(
|
|
118
|
+
"skipped unmatched apdu (line " +
|
|
119
|
+
line +
|
|
120
|
+
" – expected " +
|
|
121
|
+
head[0] +
|
|
122
|
+
")"
|
|
123
|
+
);
|
|
124
|
+
++this.passed;
|
|
125
|
+
} else {
|
|
126
|
+
throw new RecordStoreWrongAPDU(head[0], apduHex, line);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
this.queue = [];
|
|
131
|
+
throw new RecordStoreQueueEmpty();
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Check all APDUs was replayed. Throw if it's not the case.
|
|
136
|
+
*/
|
|
137
|
+
ensureQueueEmpty() {
|
|
138
|
+
if (!this.isEmpty()) {
|
|
139
|
+
throw new RecordStoreRemainingAPDU(this.toString());
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Print out the series of apdus
|
|
145
|
+
*/
|
|
146
|
+
toString(): string {
|
|
147
|
+
return (
|
|
148
|
+
this.queue
|
|
149
|
+
.map(([send, receive]) => `=> ${send}\n<= ${receive}`)
|
|
150
|
+
.join("\n") + "\n"
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Create a RecordStore by parsing a string (a series of => HEX\n<= HEX)
|
|
156
|
+
* @param {string} series of APDUs
|
|
157
|
+
* @param {$Shape<RecordStoreOptions>} opts
|
|
158
|
+
*/
|
|
159
|
+
static fromString(
|
|
160
|
+
str: string,
|
|
161
|
+
opts?: $Shape<RecordStoreOptions>
|
|
162
|
+
): RecordStore {
|
|
163
|
+
const queue: Queue = [];
|
|
164
|
+
let value = [];
|
|
165
|
+
str
|
|
166
|
+
.split("\n")
|
|
167
|
+
.map((line) => line.replace(/ /g, ""))
|
|
168
|
+
.filter((o) => o)
|
|
169
|
+
.forEach((line) => {
|
|
170
|
+
if (value.length === 0) {
|
|
171
|
+
const m = line.match(/^=>([0-9a-fA-F]+)$/);
|
|
172
|
+
if (!m) {
|
|
173
|
+
throw new RecordStoreInvalidSynthax("expected an apdu input");
|
|
174
|
+
}
|
|
175
|
+
value.push(m[1]);
|
|
176
|
+
} else {
|
|
177
|
+
const m = line.match(/^<=([0-9a-fA-F]+)$/);
|
|
178
|
+
if (!m) {
|
|
179
|
+
throw new RecordStoreInvalidSynthax("expected an apdu output");
|
|
180
|
+
}
|
|
181
|
+
value.push(m[1]);
|
|
182
|
+
queue.push([value[0], value[1]]);
|
|
183
|
+
value = [];
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
if (value.length !== 0) {
|
|
187
|
+
throw new RecordStoreInvalidSynthax("unexpected end of file");
|
|
188
|
+
}
|
|
189
|
+
return new RecordStore(queue, opts);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RecordStore.js","sourceRoot":"","sources":["../src/RecordStore.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;GAEG;AACH,MAAM,UAAU,yBAAyB,CAAC,OAAe;IACvD,IAAI,CAAC,IAAI,GAAG,2BAA2B,CAAC;IACxC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACvB,IAAI,CAAC,KAAK,GAAG,IAAI,KAAK,EAAE,CAAC,KAAK,CAAC;AACjC,CAAC;AAED,yBAAyB,CAAC,SAAS,GAAG,IAAI,KAAK,EAAE,CAAC;AAElD;;GAEG;AACH,MAAM,UAAU,qBAAqB;IACnC,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACpC,IAAI,CAAC,OAAO,GAAG,6BAA6B,CAAC;IAC7C,IAAI,CAAC,KAAK,GAAG,IAAI,KAAK,EAAE,CAAC,KAAK,CAAC;AACjC,CAAC;AAED,qBAAqB,CAAC,SAAS,GAAG,IAAI,KAAK,EAAE,CAAC;AAE9C;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAClC,QAAgB,EAChB,GAAW,EACX,IAAY;IAEZ,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACnC,IAAI,CAAC,OAAO,GAAG
|
|
1
|
+
{"version":3,"file":"RecordStore.js","sourceRoot":"","sources":["../src/RecordStore.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
//@flow
|
|
2
|
+
import Transport from "@ledgerhq/hw-transport";
|
|
3
|
+
import type { RecordStore } from "./RecordStore";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* decorate a real transport and proxy it to record the APDUs.
|
|
7
|
+
* @param {Class<Transport<*>>} DecoratedTransport: an actual transport class. Like @ledgerhq/hw-transport-webusb
|
|
8
|
+
* @param {RecordStore} recordStore: a record store to record the apdu in.
|
|
9
|
+
*/
|
|
10
|
+
const createTransportRecorder = (
|
|
11
|
+
DecoratedTransport: Class<Transport<*>>,
|
|
12
|
+
recordStore: RecordStore
|
|
13
|
+
): Class<Transport<*>> => {
|
|
14
|
+
class TransportRecorder extends Transport<*> {
|
|
15
|
+
static recordStore = recordStore;
|
|
16
|
+
static isSupported = DecoratedTransport.isSupported;
|
|
17
|
+
static list = DecoratedTransport.list;
|
|
18
|
+
static listen = DecoratedTransport.listen;
|
|
19
|
+
static open = (...args) =>
|
|
20
|
+
DecoratedTransport.open(...args).then((t) => new TransportRecorder(t));
|
|
21
|
+
setScrambleKey() {}
|
|
22
|
+
close() {
|
|
23
|
+
return this.transport.close();
|
|
24
|
+
}
|
|
25
|
+
transport: Transport<*>;
|
|
26
|
+
constructor(t) {
|
|
27
|
+
super();
|
|
28
|
+
this.transport = t;
|
|
29
|
+
}
|
|
30
|
+
exchange(apdu: Buffer): Promise<Buffer> {
|
|
31
|
+
const output = this.transport.exchange(apdu);
|
|
32
|
+
output.then((out) => {
|
|
33
|
+
recordStore.recordExchange(apdu, out);
|
|
34
|
+
});
|
|
35
|
+
return output;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return TransportRecorder;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export default createTransportRecorder;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
//@flow
|
|
2
|
+
import Transport from "@ledgerhq/hw-transport";
|
|
3
|
+
import { log } from "@ledgerhq/logs";
|
|
4
|
+
import type { RecordStore } from "./RecordStore";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* create a transport replayer with a record store.
|
|
8
|
+
* @param recordStore
|
|
9
|
+
*/
|
|
10
|
+
const createTransportReplayer = (
|
|
11
|
+
recordStore: RecordStore
|
|
12
|
+
): Class<Transport<*>> => {
|
|
13
|
+
class TransportReplayer extends Transport<*> {
|
|
14
|
+
static isSupported = () => Promise.resolve(true);
|
|
15
|
+
static list = () => Promise.resolve([null]);
|
|
16
|
+
static listen = (o) => {
|
|
17
|
+
let unsubscribed;
|
|
18
|
+
setTimeout(() => {
|
|
19
|
+
if (unsubscribed) return;
|
|
20
|
+
o.next({ type: "add", descriptor: null });
|
|
21
|
+
o.complete();
|
|
22
|
+
}, 0);
|
|
23
|
+
return {
|
|
24
|
+
unsubscribe: () => {
|
|
25
|
+
unsubscribed = true;
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
static open = () => Promise.resolve(new TransportReplayer());
|
|
30
|
+
|
|
31
|
+
setScrambleKey() {}
|
|
32
|
+
|
|
33
|
+
close() {
|
|
34
|
+
return Promise.resolve();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
exchange(apdu: Buffer): Promise<Buffer> {
|
|
38
|
+
log("apdu", apdu.toString("hex"));
|
|
39
|
+
try {
|
|
40
|
+
const buffer = recordStore.replayExchange(apdu);
|
|
41
|
+
log("apdu", buffer.toString("hex"));
|
|
42
|
+
return Promise.resolve(buffer);
|
|
43
|
+
} catch (e) {
|
|
44
|
+
log("apdu-error", String(e));
|
|
45
|
+
return Promise.reject(e);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return TransportReplayer;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export default createTransportReplayer;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ledgerhq/hw-transport-mocker",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.25.1-alpha.3+eb669e17",
|
|
4
4
|
"description": "Ledger Hardware Wallet mocker utilities used for tests",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Ledger",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"types": "lib/index.d.ts",
|
|
26
26
|
"license": "Apache-2.0",
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@ledgerhq/hw-transport": "^6.
|
|
28
|
+
"@ledgerhq/hw-transport": "^6.25.1-alpha.3+eb669e17",
|
|
29
29
|
"@ledgerhq/logs": "^6.10.0"
|
|
30
30
|
},
|
|
31
31
|
"scripts": {
|
|
@@ -33,5 +33,5 @@
|
|
|
33
33
|
"build": "bash ../../script/build.sh",
|
|
34
34
|
"watch": "bash ../../script/watch.sh"
|
|
35
35
|
},
|
|
36
|
-
"gitHead": "
|
|
36
|
+
"gitHead": "eb669e17dd87d3ab568beab1f9a5ddb1a2536e83"
|
|
37
37
|
}
|