@ledgerhq/react-native-hw-transport-ble 6.35.5 → 6.35.6-nightly.1
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 +17 -0
- package/package.json +4 -4
- package/lib/BleTransport.test.d.ts +0 -2
- package/lib/BleTransport.test.d.ts.map +0 -1
- package/lib/BleTransport.test.js +0 -343
- package/lib/BleTransport.test.js.map +0 -1
- package/lib-es/BleTransport.test.d.ts +0 -2
- package/lib-es/BleTransport.test.d.ts.map +0 -1
- package/lib-es/BleTransport.test.js +0 -338
- package/lib-es/BleTransport.test.js.map +0 -1
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
|
|
2
|
-
> @ledgerhq/react-native-hw-transport-ble@6.35.
|
|
2
|
+
> @ledgerhq/react-native-hw-transport-ble@6.35.6-nightly.0 build /home/runner/work/ledger-live/ledger-live/libs/ledgerjs/packages/react-native-hw-transport-ble
|
|
3
3
|
> tsc && tsc -m esnext --moduleResolution bundler --outDir lib-es
|
|
4
4
|
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @ledgerhq/react-native-hw-transport-ble
|
|
2
2
|
|
|
3
|
+
## 6.35.6-nightly.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [[`c1a4bfd`](https://github.com/LedgerHQ/ledger-live/commit/c1a4bfd34b46c6b6587d247673cadb3c078deb1d)]:
|
|
8
|
+
- @ledgerhq/devices@8.7.0-nightly.1
|
|
9
|
+
- @ledgerhq/hw-transport@6.31.13-nightly.1
|
|
10
|
+
|
|
11
|
+
## 6.35.6-nightly.0
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- Updated dependencies [[`759064d`](https://github.com/LedgerHQ/ledger-live/commit/759064d4815c636af2d73ba548a85b4f53e7b491)]:
|
|
16
|
+
- @ledgerhq/errors@6.27.0-nightly.0
|
|
17
|
+
- @ledgerhq/devices@8.6.2-nightly.0
|
|
18
|
+
- @ledgerhq/hw-transport@6.31.13-nightly.0
|
|
19
|
+
|
|
3
20
|
## 6.35.5
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ledgerhq/react-native-hw-transport-ble",
|
|
3
|
-
"version": "6.35.
|
|
3
|
+
"version": "6.35.6-nightly.1",
|
|
4
4
|
"description": "Ledger Hardware Wallet Bluetooth BLE transport for React Native",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Ledger",
|
|
@@ -28,9 +28,9 @@
|
|
|
28
28
|
"react-native-ble-plx": "3.4.0",
|
|
29
29
|
"rxjs": "^7.8.1",
|
|
30
30
|
"uuid": "^9.0.1",
|
|
31
|
-
"@ledgerhq/devices": "8.
|
|
32
|
-
"@ledgerhq/errors": "^6.
|
|
33
|
-
"@ledgerhq/hw-transport": "
|
|
31
|
+
"@ledgerhq/devices": "8.7.0-nightly.1",
|
|
32
|
+
"@ledgerhq/errors": "^6.27.0-nightly.0",
|
|
33
|
+
"@ledgerhq/hw-transport": "6.31.13-nightly.1",
|
|
34
34
|
"@ledgerhq/logs": "^6.13.0"
|
|
35
35
|
},
|
|
36
36
|
"gitHead": "dd0dea64b58e5a9125c8a422dcffd29e5ef6abec",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"BleTransport.test.d.ts","sourceRoot":"","sources":["../src/BleTransport.test.ts"],"names":[],"mappings":""}
|
package/lib/BleTransport.test.js
DELETED
|
@@ -1,343 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const errors_1 = require("@ledgerhq/errors");
|
|
7
|
-
const BleTransport_1 = __importDefault(require("../src/BleTransport"));
|
|
8
|
-
const rxjs_1 = require("rxjs");
|
|
9
|
-
let mockNoResponseFromDevice = false;
|
|
10
|
-
const mockCancelTransaction = jest.fn();
|
|
11
|
-
let mockNegotiatedMtu;
|
|
12
|
-
/**
|
|
13
|
-
* It is essential to mock the BLE component of a BLE transport to verify
|
|
14
|
-
* the reliability of the connect/reconnect/disconnect logic, which is decoupled
|
|
15
|
-
* from the managing logic of live-common or any other implementation.
|
|
16
|
-
* Although it may seem trivial, such an approach is necessary to ensure
|
|
17
|
-
* that the implementation is robust and dependable.
|
|
18
|
-
*
|
|
19
|
-
* To this end, a mocked react-native-ble-plx has been developed specifically
|
|
20
|
-
* to cover test cases. It should be noted that this mock is not comprehensive
|
|
21
|
-
* and may require further refinement to meet all requirements.
|
|
22
|
-
*/
|
|
23
|
-
jest.mock("react-native-ble-plx", () => {
|
|
24
|
-
class BleError {
|
|
25
|
-
iosErrorCode;
|
|
26
|
-
reason;
|
|
27
|
-
constructor(iosErrorCode, reason) {
|
|
28
|
-
this.iosErrorCode = iosErrorCode;
|
|
29
|
-
this.reason = reason;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
// Set of callbacks that we can trigger from our tests.
|
|
33
|
-
const callbacks = {};
|
|
34
|
-
return {
|
|
35
|
-
BleErrorCode: {
|
|
36
|
-
ScanStartFailed: 0,
|
|
37
|
-
},
|
|
38
|
-
BleError,
|
|
39
|
-
ConnectionPriority: {
|
|
40
|
-
Balanced: 0,
|
|
41
|
-
High: 1,
|
|
42
|
-
LowPower: 2,
|
|
43
|
-
},
|
|
44
|
-
BleManager: function () {
|
|
45
|
-
const dynamicProps = {
|
|
46
|
-
isConnected: true,
|
|
47
|
-
};
|
|
48
|
-
return {
|
|
49
|
-
onStateChange: callback => {
|
|
50
|
-
setTimeout(() => callback("PoweredOn"), 500);
|
|
51
|
-
return new rxjs_1.Subscription();
|
|
52
|
-
},
|
|
53
|
-
cancelDeviceConnection: async () => {
|
|
54
|
-
dynamicProps.isConnected = false;
|
|
55
|
-
callbacks?.onDisconnected(null);
|
|
56
|
-
},
|
|
57
|
-
devices: () => [],
|
|
58
|
-
connectedDevices: () => [],
|
|
59
|
-
connectToDevice: () => {
|
|
60
|
-
dynamicProps.isConnected = true;
|
|
61
|
-
return {
|
|
62
|
-
isConnectable: null,
|
|
63
|
-
serviceData: null,
|
|
64
|
-
overflowServiceUUIDs: null,
|
|
65
|
-
txPowerLevel: null,
|
|
66
|
-
serviceUUIDs: null,
|
|
67
|
-
rssi: null,
|
|
68
|
-
mtu: 0,
|
|
69
|
-
name: "Ledger Stax 2783",
|
|
70
|
-
localName: null,
|
|
71
|
-
id: "20EDD96F-7430-6E33-AB22-DD8AAB857CD4",
|
|
72
|
-
manufacturerData: null,
|
|
73
|
-
solicitedServiceUUIDs: null,
|
|
74
|
-
requestConnectionPriority: async () => {
|
|
75
|
-
return null; // Should return self.
|
|
76
|
-
},
|
|
77
|
-
isConnected: () => {
|
|
78
|
-
return dynamicProps.isConnected;
|
|
79
|
-
},
|
|
80
|
-
onDisconnected: callback => {
|
|
81
|
-
callbacks["onDisconnected"] = () => callback(null); // Disconnect without an error
|
|
82
|
-
return new rxjs_1.Subscription();
|
|
83
|
-
},
|
|
84
|
-
discoverAllServicesAndCharacteristics: () => { },
|
|
85
|
-
characteristicsForService: uuid => {
|
|
86
|
-
if (uuid === "13d63400-2c97-6004-0000-4c6564676572") {
|
|
87
|
-
return [
|
|
88
|
-
{
|
|
89
|
-
// Device responses
|
|
90
|
-
serviceUUID: "13d63400-2c97-6004-0000-4c6564676572",
|
|
91
|
-
isIndicatable: false,
|
|
92
|
-
isNotifiable: true,
|
|
93
|
-
isWritableWithoutResponse: false,
|
|
94
|
-
isWritableWithResponse: false,
|
|
95
|
-
serviceID: 105553179758272,
|
|
96
|
-
isReadable: false,
|
|
97
|
-
deviceID: "20EDD96F-7430-6E33-AB22-DD8AAB857CD4",
|
|
98
|
-
isNotifying: false,
|
|
99
|
-
value: "BQAAACMzIAAECTEuMC4wLXJjOQTuAAALBDUuMTUEMC4zNQEAAQCQAA==",
|
|
100
|
-
id: 105553399124864,
|
|
101
|
-
uuid: "13d63400-2c97-6004-0001-4c6564676572",
|
|
102
|
-
monitor: cb => {
|
|
103
|
-
callbacks["onDeviceResponse"] = cb;
|
|
104
|
-
return new rxjs_1.Subscription();
|
|
105
|
-
},
|
|
106
|
-
},
|
|
107
|
-
{
|
|
108
|
-
// Write
|
|
109
|
-
isNotifying: false,
|
|
110
|
-
value: null,
|
|
111
|
-
isIndicatable: false,
|
|
112
|
-
id: 105553399131872,
|
|
113
|
-
uuid: "13d63400-2c97-6004-0002-4c6564676572",
|
|
114
|
-
isReadable: false,
|
|
115
|
-
deviceID: "20EDD96F-7430-6E33-AB22-DD8AAB857CD4",
|
|
116
|
-
serviceID: 105553179758272,
|
|
117
|
-
serviceUUID: "13d63400-2c97-6004-0000-4c6564676572",
|
|
118
|
-
isWritableWithoutResponse: false,
|
|
119
|
-
isWritableWithResponse: true,
|
|
120
|
-
isNotifiable: false,
|
|
121
|
-
},
|
|
122
|
-
{
|
|
123
|
-
// Used for write without response
|
|
124
|
-
isWritableWithoutResponse: true,
|
|
125
|
-
isWritableWithResponse: false,
|
|
126
|
-
isNotifiable: false,
|
|
127
|
-
deviceID: "20EDD96F-7430-6E33-AB22-DD8AAB857CD4",
|
|
128
|
-
isReadable: false,
|
|
129
|
-
value: null,
|
|
130
|
-
isNotifying: false,
|
|
131
|
-
isIndicatable: false,
|
|
132
|
-
id: 105553399132064,
|
|
133
|
-
uuid: "13d63400-2c97-6004-0003-4c6564676572",
|
|
134
|
-
serviceUUID: "13d63400-2c97-6004-0000-4c6564676572",
|
|
135
|
-
serviceID: 105553179758272,
|
|
136
|
-
writeWithoutResponse: async (raw) => {
|
|
137
|
-
// No response are sent back from the device (using `onDeviceResponse`)
|
|
138
|
-
// Imitates the case where the device is still connected but does not responds
|
|
139
|
-
// when saving the newly confirmed seed.
|
|
140
|
-
if (mockNoResponseFromDevice) {
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
if (!dynamicProps.isConnected)
|
|
144
|
-
throw new BleError(22, "Device is not connected");
|
|
145
|
-
const hex = Buffer.from(raw, "base64").toString("hex");
|
|
146
|
-
let value;
|
|
147
|
-
switch (hex) {
|
|
148
|
-
// MTU handshake
|
|
149
|
-
case "0800000000":
|
|
150
|
-
value = mockNegotiatedMtu;
|
|
151
|
-
break;
|
|
152
|
-
// getAppAndVersion - returning BOLOS on 1.0.0-rc9
|
|
153
|
-
case "0500000005b010000000":
|
|
154
|
-
value = Buffer.from("05000000130105424f4c4f5309312e302e302d7263399000", "hex");
|
|
155
|
-
break;
|
|
156
|
-
// just used for a non resolving apdu
|
|
157
|
-
case "0500000005b020000000":
|
|
158
|
-
setTimeout(() => {
|
|
159
|
-
callbacks?.onDeviceResponse(null, {
|
|
160
|
-
value: Buffer.from("05000000029000", "hex"),
|
|
161
|
-
});
|
|
162
|
-
}, 600);
|
|
163
|
-
return; // Called after a delay to give time for the disconnect
|
|
164
|
-
default:
|
|
165
|
-
throw new Error("some generic failure");
|
|
166
|
-
}
|
|
167
|
-
// Introduce some logic to actually respond.
|
|
168
|
-
callbacks?.onDeviceResponse(null, {
|
|
169
|
-
value,
|
|
170
|
-
});
|
|
171
|
-
},
|
|
172
|
-
},
|
|
173
|
-
];
|
|
174
|
-
}
|
|
175
|
-
throw Error("Generic mocked error");
|
|
176
|
-
},
|
|
177
|
-
};
|
|
178
|
-
},
|
|
179
|
-
cancelTransaction: mockCancelTransaction,
|
|
180
|
-
};
|
|
181
|
-
},
|
|
182
|
-
};
|
|
183
|
-
});
|
|
184
|
-
describe("BleTransport connectivity test coverage", () => {
|
|
185
|
-
const deviceId = "20EDD96F-7430-6E33-AB22-DD8AAB857CD4";
|
|
186
|
-
beforeEach(() => {
|
|
187
|
-
mockNoResponseFromDevice = false;
|
|
188
|
-
// MTU of 153 bytes
|
|
189
|
-
mockNegotiatedMtu = Buffer.from("080000000099", "hex");
|
|
190
|
-
mockCancelTransaction.mockClear();
|
|
191
|
-
});
|
|
192
|
-
describe("Device available and already paired", () => {
|
|
193
|
-
it("should find the device, connect, negotiate MTU", async () => {
|
|
194
|
-
const transport = await BleTransport_1.default.open(deviceId);
|
|
195
|
-
expect(transport.device.isConnected()).toBe(true);
|
|
196
|
-
});
|
|
197
|
-
it("should be disconnectable, and cleanup", async () => {
|
|
198
|
-
const transport = await BleTransport_1.default.open(deviceId);
|
|
199
|
-
await BleTransport_1.default.disconnectDevice(deviceId);
|
|
200
|
-
expect(transport.isConnected).toBe(false);
|
|
201
|
-
});
|
|
202
|
-
it("should disconnect in 500ms (5s default) after calling close", async () => {
|
|
203
|
-
const transport = await BleTransport_1.default.open(deviceId);
|
|
204
|
-
expect(transport.isConnected).toBe(true);
|
|
205
|
-
BleTransport_1.default.disconnectTimeoutMs = 500;
|
|
206
|
-
await transport.close();
|
|
207
|
-
// Expect the timeout for disconnection to be set
|
|
208
|
-
expect(transport.disconnectTimeout).not.toBe(undefined);
|
|
209
|
-
let resolve;
|
|
210
|
-
transport.on("disconnect", () => {
|
|
211
|
-
resolve();
|
|
212
|
-
});
|
|
213
|
-
return await new Promise((_resolve, _reject) => {
|
|
214
|
-
resolve = _resolve;
|
|
215
|
-
});
|
|
216
|
-
});
|
|
217
|
-
it("should cancel disconnect if new connection is made", async () => {
|
|
218
|
-
const transport = await BleTransport_1.default.open(deviceId);
|
|
219
|
-
expect(transport.isConnected).toBe(true);
|
|
220
|
-
BleTransport_1.default.disconnectTimeoutMs = 500;
|
|
221
|
-
await transport.close();
|
|
222
|
-
// Expect the timeout for disconnection to be set
|
|
223
|
-
expect(transport.disconnectTimeout).not.toBe(undefined);
|
|
224
|
-
// Nb due to the different environments, the timeout behaves differently here
|
|
225
|
-
// and I can't check against a number for it to be cleared or not.
|
|
226
|
-
expect(transport.disconnectTimeout._destroyed).toBe(false);
|
|
227
|
-
await BleTransport_1.default.open(deviceId);
|
|
228
|
-
expect(transport.disconnectTimeout._destroyed).toBe(true);
|
|
229
|
-
});
|
|
230
|
-
it("should cancel disconnect if already disconnected", async () => {
|
|
231
|
-
const transport = await BleTransport_1.default.open(deviceId);
|
|
232
|
-
expect(transport.isConnected).toBe(true);
|
|
233
|
-
BleTransport_1.default.disconnectTimeoutMs = 500;
|
|
234
|
-
await transport.close();
|
|
235
|
-
// Expect the timeout for disconnection to be set
|
|
236
|
-
expect(transport.disconnectTimeout).not.toBe(undefined);
|
|
237
|
-
// Nb due to the different environments, the timeout behaves differently here
|
|
238
|
-
// and I can't check against a number for it to be cleared or not.
|
|
239
|
-
expect(transport.disconnectTimeout._destroyed).toBe(false);
|
|
240
|
-
await BleTransport_1.default.disconnectDevice(deviceId);
|
|
241
|
-
expect(transport.disconnectTimeout._destroyed).toBe(true);
|
|
242
|
-
});
|
|
243
|
-
describe("When the message to exchange fits in 1 frame", () => {
|
|
244
|
-
it("should handle exchanges if all goes well", async () => {
|
|
245
|
-
const transport = await BleTransport_1.default.open(deviceId);
|
|
246
|
-
expect(transport.isConnected).toBe(true);
|
|
247
|
-
const response = await transport.exchange(Buffer.from("b010000000", "hex"));
|
|
248
|
-
expect(response.toString("hex")).toBe("0105424f4c4f5309312e302e302d7263399000");
|
|
249
|
-
});
|
|
250
|
-
it("should throw on exchanges if disconnected", async () => {
|
|
251
|
-
const transport = await BleTransport_1.default.open(deviceId);
|
|
252
|
-
expect(transport.isConnected).toBe(true);
|
|
253
|
-
await BleTransport_1.default.disconnectDevice(deviceId);
|
|
254
|
-
await expect(transport.exchange(Buffer.from("b010000000", "hex"))).rejects.toThrow(); // More specific errors some day.
|
|
255
|
-
});
|
|
256
|
-
describe("And when an abort timeout is set", () => {
|
|
257
|
-
const abortTimeoutMs = 1000;
|
|
258
|
-
it("should throw an error and cancel the transaction if the abort timeout was reached", done => {
|
|
259
|
-
const rxjsScheduler = new rxjs_1.VirtualTimeScheduler();
|
|
260
|
-
async function asyncFn() {
|
|
261
|
-
const transport = await BleTransport_1.default.open(deviceId);
|
|
262
|
-
expect(transport.isConnected).toBe(true);
|
|
263
|
-
// Once we got the transport (MTU exchanged), we stop the communication
|
|
264
|
-
mockNoResponseFromDevice = true;
|
|
265
|
-
transport
|
|
266
|
-
.exchange(Buffer.from("b010000000", "hex"), { abortTimeoutMs })
|
|
267
|
-
.then(() => {
|
|
268
|
-
done("It should not succeed");
|
|
269
|
-
})
|
|
270
|
-
.catch(error => {
|
|
271
|
-
expect(error).toBeInstanceOf(errors_1.TransportExchangeTimeoutError);
|
|
272
|
-
expect(mockCancelTransaction).toHaveBeenCalledTimes(1);
|
|
273
|
-
done();
|
|
274
|
-
});
|
|
275
|
-
rxjsScheduler.flush();
|
|
276
|
-
}
|
|
277
|
-
asyncFn();
|
|
278
|
-
});
|
|
279
|
-
});
|
|
280
|
-
});
|
|
281
|
-
// Multi-frames message response is not handled by our current mocked react-native-ble-plx
|
|
282
|
-
// The logic of encoding a message into several frames is tested directly with unit tests on ledgerhq/devices/lib/ble/sendAPDU
|
|
283
|
-
describe("When the message to exchange needs more than 1 frame", () => {
|
|
284
|
-
beforeEach(async () => {
|
|
285
|
-
// Triggering a disconnection and clearing the transport cache
|
|
286
|
-
await BleTransport_1.default.disconnectDevice(deviceId);
|
|
287
|
-
// MTU of 25 bytes
|
|
288
|
-
mockNegotiatedMtu = Buffer.from("080000000019", "hex");
|
|
289
|
-
});
|
|
290
|
-
afterEach(async () => {
|
|
291
|
-
// Triggering a disconnection and clearing the transport cache
|
|
292
|
-
await BleTransport_1.default.disconnectDevice(deviceId);
|
|
293
|
-
});
|
|
294
|
-
describe("And when an abort timeout is set", () => {
|
|
295
|
-
const abortTimeoutMs = 1000;
|
|
296
|
-
it("should throw an error and cancel the transactions of all operations if the abort timeout was reached", done => {
|
|
297
|
-
const rxjsScheduler = new rxjs_1.VirtualTimeScheduler();
|
|
298
|
-
async function asyncFn() {
|
|
299
|
-
const transport = await BleTransport_1.default.open(deviceId);
|
|
300
|
-
expect(transport.isConnected).toBe(true);
|
|
301
|
-
// Once we got the transport (MTU exchanged), we stop the communication
|
|
302
|
-
mockNoResponseFromDevice = true;
|
|
303
|
-
// Imaginary APDU that will create an encoded message longer than MTU = 25 bytes
|
|
304
|
-
transport
|
|
305
|
-
.exchange(Buffer.from("b010000000b010000000b010000000b010000000b010000000", "hex"), {
|
|
306
|
-
abortTimeoutMs,
|
|
307
|
-
})
|
|
308
|
-
.then(() => {
|
|
309
|
-
done("It should not succeed");
|
|
310
|
-
})
|
|
311
|
-
.catch(error => {
|
|
312
|
-
expect(error).toBeInstanceOf(errors_1.TransportExchangeTimeoutError);
|
|
313
|
-
expect(mockCancelTransaction).toHaveBeenCalledTimes(2);
|
|
314
|
-
done();
|
|
315
|
-
});
|
|
316
|
-
rxjsScheduler.flush();
|
|
317
|
-
}
|
|
318
|
-
asyncFn();
|
|
319
|
-
});
|
|
320
|
-
});
|
|
321
|
-
});
|
|
322
|
-
it("should disconnect if close is called, even if pending response", done => {
|
|
323
|
-
// This is actually a very important test, if we have an ongoing apdu response,
|
|
324
|
-
// as in, the device never replied, but we expressed the intention of disconnecting
|
|
325
|
-
// we will give it a few seconds and then disconnect regardless. Otherwise we fall
|
|
326
|
-
// in the never ending await trap.
|
|
327
|
-
async function asyncFn() {
|
|
328
|
-
const transport = await BleTransport_1.default.open(deviceId);
|
|
329
|
-
expect(transport.isConnected).toBe(true);
|
|
330
|
-
transport.exchange(Buffer.from("b020000000", "hex"));
|
|
331
|
-
BleTransport_1.default.disconnectTimeoutMs = 500;
|
|
332
|
-
transport.on("disconnect", () => {
|
|
333
|
-
done(); // If this is never called, then we're still waiting.
|
|
334
|
-
});
|
|
335
|
-
await transport.close();
|
|
336
|
-
// Expect the timeout for disconnection to be set
|
|
337
|
-
expect(transport.disconnectTimeout).not.toBe(undefined);
|
|
338
|
-
}
|
|
339
|
-
asyncFn();
|
|
340
|
-
});
|
|
341
|
-
});
|
|
342
|
-
});
|
|
343
|
-
//# sourceMappingURL=BleTransport.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"BleTransport.test.js","sourceRoot":"","sources":["../src/BleTransport.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"BleTransport.test.d.ts","sourceRoot":"","sources":["../src/BleTransport.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,338 +0,0 @@
|
|
|
1
|
-
import { TransportExchangeTimeoutError } from "@ledgerhq/errors";
|
|
2
|
-
import BleTransport from "../src/BleTransport";
|
|
3
|
-
import { Subscription, VirtualTimeScheduler } from "rxjs";
|
|
4
|
-
let mockNoResponseFromDevice = false;
|
|
5
|
-
const mockCancelTransaction = jest.fn();
|
|
6
|
-
let mockNegotiatedMtu;
|
|
7
|
-
/**
|
|
8
|
-
* It is essential to mock the BLE component of a BLE transport to verify
|
|
9
|
-
* the reliability of the connect/reconnect/disconnect logic, which is decoupled
|
|
10
|
-
* from the managing logic of live-common or any other implementation.
|
|
11
|
-
* Although it may seem trivial, such an approach is necessary to ensure
|
|
12
|
-
* that the implementation is robust and dependable.
|
|
13
|
-
*
|
|
14
|
-
* To this end, a mocked react-native-ble-plx has been developed specifically
|
|
15
|
-
* to cover test cases. It should be noted that this mock is not comprehensive
|
|
16
|
-
* and may require further refinement to meet all requirements.
|
|
17
|
-
*/
|
|
18
|
-
jest.mock("react-native-ble-plx", () => {
|
|
19
|
-
class BleError {
|
|
20
|
-
iosErrorCode;
|
|
21
|
-
reason;
|
|
22
|
-
constructor(iosErrorCode, reason) {
|
|
23
|
-
this.iosErrorCode = iosErrorCode;
|
|
24
|
-
this.reason = reason;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
// Set of callbacks that we can trigger from our tests.
|
|
28
|
-
const callbacks = {};
|
|
29
|
-
return {
|
|
30
|
-
BleErrorCode: {
|
|
31
|
-
ScanStartFailed: 0,
|
|
32
|
-
},
|
|
33
|
-
BleError,
|
|
34
|
-
ConnectionPriority: {
|
|
35
|
-
Balanced: 0,
|
|
36
|
-
High: 1,
|
|
37
|
-
LowPower: 2,
|
|
38
|
-
},
|
|
39
|
-
BleManager: function () {
|
|
40
|
-
const dynamicProps = {
|
|
41
|
-
isConnected: true,
|
|
42
|
-
};
|
|
43
|
-
return {
|
|
44
|
-
onStateChange: callback => {
|
|
45
|
-
setTimeout(() => callback("PoweredOn"), 500);
|
|
46
|
-
return new Subscription();
|
|
47
|
-
},
|
|
48
|
-
cancelDeviceConnection: async () => {
|
|
49
|
-
dynamicProps.isConnected = false;
|
|
50
|
-
callbacks?.onDisconnected(null);
|
|
51
|
-
},
|
|
52
|
-
devices: () => [],
|
|
53
|
-
connectedDevices: () => [],
|
|
54
|
-
connectToDevice: () => {
|
|
55
|
-
dynamicProps.isConnected = true;
|
|
56
|
-
return {
|
|
57
|
-
isConnectable: null,
|
|
58
|
-
serviceData: null,
|
|
59
|
-
overflowServiceUUIDs: null,
|
|
60
|
-
txPowerLevel: null,
|
|
61
|
-
serviceUUIDs: null,
|
|
62
|
-
rssi: null,
|
|
63
|
-
mtu: 0,
|
|
64
|
-
name: "Ledger Stax 2783",
|
|
65
|
-
localName: null,
|
|
66
|
-
id: "20EDD96F-7430-6E33-AB22-DD8AAB857CD4",
|
|
67
|
-
manufacturerData: null,
|
|
68
|
-
solicitedServiceUUIDs: null,
|
|
69
|
-
requestConnectionPriority: async () => {
|
|
70
|
-
return null; // Should return self.
|
|
71
|
-
},
|
|
72
|
-
isConnected: () => {
|
|
73
|
-
return dynamicProps.isConnected;
|
|
74
|
-
},
|
|
75
|
-
onDisconnected: callback => {
|
|
76
|
-
callbacks["onDisconnected"] = () => callback(null); // Disconnect without an error
|
|
77
|
-
return new Subscription();
|
|
78
|
-
},
|
|
79
|
-
discoverAllServicesAndCharacteristics: () => { },
|
|
80
|
-
characteristicsForService: uuid => {
|
|
81
|
-
if (uuid === "13d63400-2c97-6004-0000-4c6564676572") {
|
|
82
|
-
return [
|
|
83
|
-
{
|
|
84
|
-
// Device responses
|
|
85
|
-
serviceUUID: "13d63400-2c97-6004-0000-4c6564676572",
|
|
86
|
-
isIndicatable: false,
|
|
87
|
-
isNotifiable: true,
|
|
88
|
-
isWritableWithoutResponse: false,
|
|
89
|
-
isWritableWithResponse: false,
|
|
90
|
-
serviceID: 105553179758272,
|
|
91
|
-
isReadable: false,
|
|
92
|
-
deviceID: "20EDD96F-7430-6E33-AB22-DD8AAB857CD4",
|
|
93
|
-
isNotifying: false,
|
|
94
|
-
value: "BQAAACMzIAAECTEuMC4wLXJjOQTuAAALBDUuMTUEMC4zNQEAAQCQAA==",
|
|
95
|
-
id: 105553399124864,
|
|
96
|
-
uuid: "13d63400-2c97-6004-0001-4c6564676572",
|
|
97
|
-
monitor: cb => {
|
|
98
|
-
callbacks["onDeviceResponse"] = cb;
|
|
99
|
-
return new Subscription();
|
|
100
|
-
},
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
// Write
|
|
104
|
-
isNotifying: false,
|
|
105
|
-
value: null,
|
|
106
|
-
isIndicatable: false,
|
|
107
|
-
id: 105553399131872,
|
|
108
|
-
uuid: "13d63400-2c97-6004-0002-4c6564676572",
|
|
109
|
-
isReadable: false,
|
|
110
|
-
deviceID: "20EDD96F-7430-6E33-AB22-DD8AAB857CD4",
|
|
111
|
-
serviceID: 105553179758272,
|
|
112
|
-
serviceUUID: "13d63400-2c97-6004-0000-4c6564676572",
|
|
113
|
-
isWritableWithoutResponse: false,
|
|
114
|
-
isWritableWithResponse: true,
|
|
115
|
-
isNotifiable: false,
|
|
116
|
-
},
|
|
117
|
-
{
|
|
118
|
-
// Used for write without response
|
|
119
|
-
isWritableWithoutResponse: true,
|
|
120
|
-
isWritableWithResponse: false,
|
|
121
|
-
isNotifiable: false,
|
|
122
|
-
deviceID: "20EDD96F-7430-6E33-AB22-DD8AAB857CD4",
|
|
123
|
-
isReadable: false,
|
|
124
|
-
value: null,
|
|
125
|
-
isNotifying: false,
|
|
126
|
-
isIndicatable: false,
|
|
127
|
-
id: 105553399132064,
|
|
128
|
-
uuid: "13d63400-2c97-6004-0003-4c6564676572",
|
|
129
|
-
serviceUUID: "13d63400-2c97-6004-0000-4c6564676572",
|
|
130
|
-
serviceID: 105553179758272,
|
|
131
|
-
writeWithoutResponse: async (raw) => {
|
|
132
|
-
// No response are sent back from the device (using `onDeviceResponse`)
|
|
133
|
-
// Imitates the case where the device is still connected but does not responds
|
|
134
|
-
// when saving the newly confirmed seed.
|
|
135
|
-
if (mockNoResponseFromDevice) {
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
|
-
if (!dynamicProps.isConnected)
|
|
139
|
-
throw new BleError(22, "Device is not connected");
|
|
140
|
-
const hex = Buffer.from(raw, "base64").toString("hex");
|
|
141
|
-
let value;
|
|
142
|
-
switch (hex) {
|
|
143
|
-
// MTU handshake
|
|
144
|
-
case "0800000000":
|
|
145
|
-
value = mockNegotiatedMtu;
|
|
146
|
-
break;
|
|
147
|
-
// getAppAndVersion - returning BOLOS on 1.0.0-rc9
|
|
148
|
-
case "0500000005b010000000":
|
|
149
|
-
value = Buffer.from("05000000130105424f4c4f5309312e302e302d7263399000", "hex");
|
|
150
|
-
break;
|
|
151
|
-
// just used for a non resolving apdu
|
|
152
|
-
case "0500000005b020000000":
|
|
153
|
-
setTimeout(() => {
|
|
154
|
-
callbacks?.onDeviceResponse(null, {
|
|
155
|
-
value: Buffer.from("05000000029000", "hex"),
|
|
156
|
-
});
|
|
157
|
-
}, 600);
|
|
158
|
-
return; // Called after a delay to give time for the disconnect
|
|
159
|
-
default:
|
|
160
|
-
throw new Error("some generic failure");
|
|
161
|
-
}
|
|
162
|
-
// Introduce some logic to actually respond.
|
|
163
|
-
callbacks?.onDeviceResponse(null, {
|
|
164
|
-
value,
|
|
165
|
-
});
|
|
166
|
-
},
|
|
167
|
-
},
|
|
168
|
-
];
|
|
169
|
-
}
|
|
170
|
-
throw Error("Generic mocked error");
|
|
171
|
-
},
|
|
172
|
-
};
|
|
173
|
-
},
|
|
174
|
-
cancelTransaction: mockCancelTransaction,
|
|
175
|
-
};
|
|
176
|
-
},
|
|
177
|
-
};
|
|
178
|
-
});
|
|
179
|
-
describe("BleTransport connectivity test coverage", () => {
|
|
180
|
-
const deviceId = "20EDD96F-7430-6E33-AB22-DD8AAB857CD4";
|
|
181
|
-
beforeEach(() => {
|
|
182
|
-
mockNoResponseFromDevice = false;
|
|
183
|
-
// MTU of 153 bytes
|
|
184
|
-
mockNegotiatedMtu = Buffer.from("080000000099", "hex");
|
|
185
|
-
mockCancelTransaction.mockClear();
|
|
186
|
-
});
|
|
187
|
-
describe("Device available and already paired", () => {
|
|
188
|
-
it("should find the device, connect, negotiate MTU", async () => {
|
|
189
|
-
const transport = await BleTransport.open(deviceId);
|
|
190
|
-
expect(transport.device.isConnected()).toBe(true);
|
|
191
|
-
});
|
|
192
|
-
it("should be disconnectable, and cleanup", async () => {
|
|
193
|
-
const transport = await BleTransport.open(deviceId);
|
|
194
|
-
await BleTransport.disconnectDevice(deviceId);
|
|
195
|
-
expect(transport.isConnected).toBe(false);
|
|
196
|
-
});
|
|
197
|
-
it("should disconnect in 500ms (5s default) after calling close", async () => {
|
|
198
|
-
const transport = await BleTransport.open(deviceId);
|
|
199
|
-
expect(transport.isConnected).toBe(true);
|
|
200
|
-
BleTransport.disconnectTimeoutMs = 500;
|
|
201
|
-
await transport.close();
|
|
202
|
-
// Expect the timeout for disconnection to be set
|
|
203
|
-
expect(transport.disconnectTimeout).not.toBe(undefined);
|
|
204
|
-
let resolve;
|
|
205
|
-
transport.on("disconnect", () => {
|
|
206
|
-
resolve();
|
|
207
|
-
});
|
|
208
|
-
return await new Promise((_resolve, _reject) => {
|
|
209
|
-
resolve = _resolve;
|
|
210
|
-
});
|
|
211
|
-
});
|
|
212
|
-
it("should cancel disconnect if new connection is made", async () => {
|
|
213
|
-
const transport = await BleTransport.open(deviceId);
|
|
214
|
-
expect(transport.isConnected).toBe(true);
|
|
215
|
-
BleTransport.disconnectTimeoutMs = 500;
|
|
216
|
-
await transport.close();
|
|
217
|
-
// Expect the timeout for disconnection to be set
|
|
218
|
-
expect(transport.disconnectTimeout).not.toBe(undefined);
|
|
219
|
-
// Nb due to the different environments, the timeout behaves differently here
|
|
220
|
-
// and I can't check against a number for it to be cleared or not.
|
|
221
|
-
expect(transport.disconnectTimeout._destroyed).toBe(false);
|
|
222
|
-
await BleTransport.open(deviceId);
|
|
223
|
-
expect(transport.disconnectTimeout._destroyed).toBe(true);
|
|
224
|
-
});
|
|
225
|
-
it("should cancel disconnect if already disconnected", async () => {
|
|
226
|
-
const transport = await BleTransport.open(deviceId);
|
|
227
|
-
expect(transport.isConnected).toBe(true);
|
|
228
|
-
BleTransport.disconnectTimeoutMs = 500;
|
|
229
|
-
await transport.close();
|
|
230
|
-
// Expect the timeout for disconnection to be set
|
|
231
|
-
expect(transport.disconnectTimeout).not.toBe(undefined);
|
|
232
|
-
// Nb due to the different environments, the timeout behaves differently here
|
|
233
|
-
// and I can't check against a number for it to be cleared or not.
|
|
234
|
-
expect(transport.disconnectTimeout._destroyed).toBe(false);
|
|
235
|
-
await BleTransport.disconnectDevice(deviceId);
|
|
236
|
-
expect(transport.disconnectTimeout._destroyed).toBe(true);
|
|
237
|
-
});
|
|
238
|
-
describe("When the message to exchange fits in 1 frame", () => {
|
|
239
|
-
it("should handle exchanges if all goes well", async () => {
|
|
240
|
-
const transport = await BleTransport.open(deviceId);
|
|
241
|
-
expect(transport.isConnected).toBe(true);
|
|
242
|
-
const response = await transport.exchange(Buffer.from("b010000000", "hex"));
|
|
243
|
-
expect(response.toString("hex")).toBe("0105424f4c4f5309312e302e302d7263399000");
|
|
244
|
-
});
|
|
245
|
-
it("should throw on exchanges if disconnected", async () => {
|
|
246
|
-
const transport = await BleTransport.open(deviceId);
|
|
247
|
-
expect(transport.isConnected).toBe(true);
|
|
248
|
-
await BleTransport.disconnectDevice(deviceId);
|
|
249
|
-
await expect(transport.exchange(Buffer.from("b010000000", "hex"))).rejects.toThrow(); // More specific errors some day.
|
|
250
|
-
});
|
|
251
|
-
describe("And when an abort timeout is set", () => {
|
|
252
|
-
const abortTimeoutMs = 1000;
|
|
253
|
-
it("should throw an error and cancel the transaction if the abort timeout was reached", done => {
|
|
254
|
-
const rxjsScheduler = new VirtualTimeScheduler();
|
|
255
|
-
async function asyncFn() {
|
|
256
|
-
const transport = await BleTransport.open(deviceId);
|
|
257
|
-
expect(transport.isConnected).toBe(true);
|
|
258
|
-
// Once we got the transport (MTU exchanged), we stop the communication
|
|
259
|
-
mockNoResponseFromDevice = true;
|
|
260
|
-
transport
|
|
261
|
-
.exchange(Buffer.from("b010000000", "hex"), { abortTimeoutMs })
|
|
262
|
-
.then(() => {
|
|
263
|
-
done("It should not succeed");
|
|
264
|
-
})
|
|
265
|
-
.catch(error => {
|
|
266
|
-
expect(error).toBeInstanceOf(TransportExchangeTimeoutError);
|
|
267
|
-
expect(mockCancelTransaction).toHaveBeenCalledTimes(1);
|
|
268
|
-
done();
|
|
269
|
-
});
|
|
270
|
-
rxjsScheduler.flush();
|
|
271
|
-
}
|
|
272
|
-
asyncFn();
|
|
273
|
-
});
|
|
274
|
-
});
|
|
275
|
-
});
|
|
276
|
-
// Multi-frames message response is not handled by our current mocked react-native-ble-plx
|
|
277
|
-
// The logic of encoding a message into several frames is tested directly with unit tests on ledgerhq/devices/lib/ble/sendAPDU
|
|
278
|
-
describe("When the message to exchange needs more than 1 frame", () => {
|
|
279
|
-
beforeEach(async () => {
|
|
280
|
-
// Triggering a disconnection and clearing the transport cache
|
|
281
|
-
await BleTransport.disconnectDevice(deviceId);
|
|
282
|
-
// MTU of 25 bytes
|
|
283
|
-
mockNegotiatedMtu = Buffer.from("080000000019", "hex");
|
|
284
|
-
});
|
|
285
|
-
afterEach(async () => {
|
|
286
|
-
// Triggering a disconnection and clearing the transport cache
|
|
287
|
-
await BleTransport.disconnectDevice(deviceId);
|
|
288
|
-
});
|
|
289
|
-
describe("And when an abort timeout is set", () => {
|
|
290
|
-
const abortTimeoutMs = 1000;
|
|
291
|
-
it("should throw an error and cancel the transactions of all operations if the abort timeout was reached", done => {
|
|
292
|
-
const rxjsScheduler = new VirtualTimeScheduler();
|
|
293
|
-
async function asyncFn() {
|
|
294
|
-
const transport = await BleTransport.open(deviceId);
|
|
295
|
-
expect(transport.isConnected).toBe(true);
|
|
296
|
-
// Once we got the transport (MTU exchanged), we stop the communication
|
|
297
|
-
mockNoResponseFromDevice = true;
|
|
298
|
-
// Imaginary APDU that will create an encoded message longer than MTU = 25 bytes
|
|
299
|
-
transport
|
|
300
|
-
.exchange(Buffer.from("b010000000b010000000b010000000b010000000b010000000", "hex"), {
|
|
301
|
-
abortTimeoutMs,
|
|
302
|
-
})
|
|
303
|
-
.then(() => {
|
|
304
|
-
done("It should not succeed");
|
|
305
|
-
})
|
|
306
|
-
.catch(error => {
|
|
307
|
-
expect(error).toBeInstanceOf(TransportExchangeTimeoutError);
|
|
308
|
-
expect(mockCancelTransaction).toHaveBeenCalledTimes(2);
|
|
309
|
-
done();
|
|
310
|
-
});
|
|
311
|
-
rxjsScheduler.flush();
|
|
312
|
-
}
|
|
313
|
-
asyncFn();
|
|
314
|
-
});
|
|
315
|
-
});
|
|
316
|
-
});
|
|
317
|
-
it("should disconnect if close is called, even if pending response", done => {
|
|
318
|
-
// This is actually a very important test, if we have an ongoing apdu response,
|
|
319
|
-
// as in, the device never replied, but we expressed the intention of disconnecting
|
|
320
|
-
// we will give it a few seconds and then disconnect regardless. Otherwise we fall
|
|
321
|
-
// in the never ending await trap.
|
|
322
|
-
async function asyncFn() {
|
|
323
|
-
const transport = await BleTransport.open(deviceId);
|
|
324
|
-
expect(transport.isConnected).toBe(true);
|
|
325
|
-
transport.exchange(Buffer.from("b020000000", "hex"));
|
|
326
|
-
BleTransport.disconnectTimeoutMs = 500;
|
|
327
|
-
transport.on("disconnect", () => {
|
|
328
|
-
done(); // If this is never called, then we're still waiting.
|
|
329
|
-
});
|
|
330
|
-
await transport.close();
|
|
331
|
-
// Expect the timeout for disconnection to be set
|
|
332
|
-
expect(transport.disconnectTimeout).not.toBe(undefined);
|
|
333
|
-
}
|
|
334
|
-
asyncFn();
|
|
335
|
-
});
|
|
336
|
-
});
|
|
337
|
-
});
|
|
338
|
-
//# sourceMappingURL=BleTransport.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"BleTransport.test.js","sourceRoot":"","sources":["../src/BleTransport.test.ts"],"names":[],"mappings":"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"}
|