@ledgerhq/react-native-hw-transport-ble 6.28.3 → 6.28.4-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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +17 -0
- package/lib/BleTransport.d.ts +67 -37
- package/lib/BleTransport.d.ts.map +1 -1
- package/lib/BleTransport.js +257 -198
- package/lib/BleTransport.js.map +1 -1
- package/lib/BleTransport.test.d.ts +2 -0
- package/lib/BleTransport.test.d.ts.map +1 -0
- package/lib/BleTransport.test.js +370 -0
- package/lib/BleTransport.test.js.map +1 -0
- package/lib/remapErrors.d.ts +4 -0
- package/lib/remapErrors.d.ts.map +1 -1
- package/lib/remapErrors.js +20 -1
- package/lib/remapErrors.js.map +1 -1
- package/lib/types.d.ts +4 -0
- package/lib/types.d.ts.map +1 -1
- package/lib-es/BleTransport.d.ts +67 -37
- package/lib-es/BleTransport.d.ts.map +1 -1
- package/lib-es/BleTransport.js +257 -198
- package/lib-es/BleTransport.js.map +1 -1
- package/lib-es/BleTransport.test.d.ts +2 -0
- package/lib-es/BleTransport.test.d.ts.map +1 -0
- package/lib-es/BleTransport.test.js +365 -0
- package/lib-es/BleTransport.test.js.map +1 -0
- package/lib-es/remapErrors.d.ts +4 -0
- package/lib-es/remapErrors.d.ts.map +1 -1
- package/lib-es/remapErrors.js +19 -1
- package/lib-es/remapErrors.js.map +1 -1
- package/lib-es/types.d.ts +4 -0
- package/lib-es/types.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/BleTransport.test.ts +275 -0
- package/src/BleTransport.ts +250 -172
- package/src/remapErrors.ts +33 -2
- package/src/types.ts +5 -0
package/lib/BleTransport.js
CHANGED
|
@@ -82,10 +82,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
82
82
|
};
|
|
83
83
|
exports.__esModule = true;
|
|
84
84
|
exports.setReconnectionConfig = void 0;
|
|
85
|
-
/* eslint-disable prefer-template */
|
|
86
85
|
var hw_transport_1 = __importDefault(require("@ledgerhq/hw-transport"));
|
|
87
|
-
var react_native_ble_plx_1 = require("react-native-ble-plx");
|
|
88
|
-
var devices_1 = require("@ledgerhq/devices");
|
|
89
86
|
// ---------------------------------------------------------------------------------------------
|
|
90
87
|
// Since this is a react-native library and metro bundler does not support
|
|
91
88
|
// package exports yet (see: https://github.com/facebook/metro/issues/670)
|
|
@@ -96,6 +93,8 @@ var devices_1 = require("@ledgerhq/devices");
|
|
|
96
93
|
// See: https://github.com/LedgerHQ/ledger-live/pull/879
|
|
97
94
|
var sendAPDU_1 = require("@ledgerhq/devices/lib/ble/sendAPDU");
|
|
98
95
|
var receiveAPDU_1 = require("@ledgerhq/devices/lib/ble/receiveAPDU");
|
|
96
|
+
var react_native_ble_plx_1 = require("react-native-ble-plx");
|
|
97
|
+
var devices_1 = require("@ledgerhq/devices");
|
|
99
98
|
var logs_1 = require("@ledgerhq/logs");
|
|
100
99
|
var rxjs_1 = require("rxjs");
|
|
101
100
|
var operators_1 = require("rxjs/operators");
|
|
@@ -103,25 +102,18 @@ var errors_1 = require("@ledgerhq/errors");
|
|
|
103
102
|
var monitorCharacteristic_1 = require("./monitorCharacteristic");
|
|
104
103
|
var awaitsBleOn_1 = require("./awaitsBleOn");
|
|
105
104
|
var remapErrors_1 = require("./remapErrors");
|
|
106
|
-
var connectOptions = {
|
|
107
|
-
requestMTU: 156,
|
|
108
|
-
connectionPriority: 1
|
|
109
|
-
};
|
|
110
|
-
var transportsCache = {};
|
|
111
|
-
var _bleManager = null;
|
|
112
105
|
/**
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
* Do not use _bleManager directly
|
|
117
|
-
* Only use this instance getter inside BleTransport
|
|
106
|
+
* This is potentially not needed anymore, to be checked if the bug is still
|
|
107
|
+
* happening.
|
|
118
108
|
*/
|
|
119
|
-
var
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
109
|
+
var reconnectionConfig = {
|
|
110
|
+
pairingThreshold: 1000,
|
|
111
|
+
delayAfterFirstPairing: 4000
|
|
112
|
+
};
|
|
113
|
+
var setReconnectionConfig = function (config) {
|
|
114
|
+
reconnectionConfig = config;
|
|
124
115
|
};
|
|
116
|
+
exports.setReconnectionConfig = setReconnectionConfig;
|
|
125
117
|
var retrieveInfos = function (device) {
|
|
126
118
|
if (!device || !device.serviceUUIDs)
|
|
127
119
|
return;
|
|
@@ -133,147 +125,168 @@ var retrieveInfos = function (device) {
|
|
|
133
125
|
return;
|
|
134
126
|
return infos;
|
|
135
127
|
};
|
|
136
|
-
var
|
|
137
|
-
|
|
138
|
-
|
|
128
|
+
var delay = function (ms) {
|
|
129
|
+
return new Promise(function (success) { return setTimeout(success, ms); });
|
|
130
|
+
};
|
|
131
|
+
/**
|
|
132
|
+
* A cache of Bluetooth transport instances associated with device IDs.
|
|
133
|
+
* Allows efficient storage and retrieval of previously initialized transports.
|
|
134
|
+
* @type {Object.<string, BluetoothTransport>}
|
|
135
|
+
*/
|
|
136
|
+
var transportsCache = {};
|
|
137
|
+
/**
|
|
138
|
+
* Returns the instance of the Bluetooth Low Energy Manager. It initializes it only
|
|
139
|
+
* when it's first needed, preventing the permission prompt happening prematurely.
|
|
140
|
+
* Important: Do NOT access the _bleManager variable directly.
|
|
141
|
+
* Use this function instead.
|
|
142
|
+
* @returns {BleManager} - The instance of the BleManager.
|
|
143
|
+
*/
|
|
144
|
+
var _bleManager = null;
|
|
145
|
+
var bleManagerInstance = function () {
|
|
146
|
+
if (!_bleManager) {
|
|
147
|
+
_bleManager = new react_native_ble_plx_1.BleManager();
|
|
148
|
+
}
|
|
149
|
+
return _bleManager;
|
|
150
|
+
};
|
|
151
|
+
var clearDisconnectTimeout = function (deviceId) {
|
|
152
|
+
var cachedTransport = transportsCache[deviceId];
|
|
153
|
+
if (cachedTransport && cachedTransport.disconnectTimeout) {
|
|
154
|
+
(0, logs_1.log)(TAG, "Clearing queued disconnect");
|
|
155
|
+
clearTimeout(cachedTransport.disconnectTimeout);
|
|
156
|
+
}
|
|
139
157
|
};
|
|
140
|
-
function setReconnectionConfig(config) {
|
|
141
|
-
reconnectionConfig = config;
|
|
142
|
-
}
|
|
143
|
-
exports.setReconnectionConfig = setReconnectionConfig;
|
|
144
|
-
var delay = function (ms) { return new Promise(function (success) { return setTimeout(success, ms); }); };
|
|
145
158
|
function open(deviceOrId, needsReconnect) {
|
|
146
159
|
return __awaiter(this, void 0, void 0, function () {
|
|
147
|
-
var device, devices, connectedDevices, connectedDevicesFiltered, e_1, e_2, res, characteristics, _a, _b, uuid, e_3, e_4_1, deviceModel, serviceUuid, writeUuid, writeCmdUuid, notifyUuid, writeC, writeCmdC, notifyC, characteristics_1, characteristics_1_1, c, notifyObservable, notif, transport,
|
|
160
|
+
var device, devices, connectedDevices, connectedDevicesFiltered, e_1, e_2, res, characteristics, _a, _b, uuid, e_3, e_4_1, deviceModel, serviceUuid, writeUuid, writeCmdUuid, notifyUuid, writeC, writeCmdC, notifyC, characteristics_1, characteristics_1_1, c, notifyObservable, notif, transport, disconnectedSub, onDisconnect, beforeMTUTime, afterMTUTime;
|
|
148
161
|
var _c, _d, e_4, _e, e_5, _f;
|
|
149
162
|
return __generator(this, function (_g) {
|
|
150
163
|
switch (_g.label) {
|
|
151
164
|
case 0:
|
|
152
|
-
|
|
165
|
+
(0, logs_1.log)(TAG, "open with ".concat(deviceOrId));
|
|
166
|
+
if (!(typeof deviceOrId === "string")) return [3 /*break*/, 12];
|
|
153
167
|
if (transportsCache[deviceOrId]) {
|
|
154
|
-
(0, logs_1.log)(
|
|
168
|
+
(0, logs_1.log)(TAG, "Transport in cache, using that.");
|
|
169
|
+
clearDisconnectTimeout(deviceOrId);
|
|
155
170
|
return [2 /*return*/, transportsCache[deviceOrId]];
|
|
156
171
|
}
|
|
157
|
-
(0, logs_1.log)(
|
|
172
|
+
(0, logs_1.log)(TAG, "Tries to open device: ".concat(deviceOrId));
|
|
158
173
|
return [4 /*yield*/, (0, awaitsBleOn_1.awaitsBleOn)(bleManagerInstance())];
|
|
159
174
|
case 1:
|
|
160
175
|
_g.sent();
|
|
161
|
-
if (!!device) return [3 /*break*/, 3];
|
|
162
176
|
return [4 /*yield*/, bleManagerInstance().devices([deviceOrId])];
|
|
163
177
|
case 2:
|
|
164
178
|
devices = _g.sent();
|
|
165
|
-
(0, logs_1.log)(
|
|
179
|
+
(0, logs_1.log)(TAG, "found ".concat(devices.length, " devices"));
|
|
166
180
|
_c = __read(devices, 1), device = _c[0];
|
|
167
|
-
|
|
168
|
-
case 3:
|
|
169
|
-
if (!!device) return [3 /*break*/, 5];
|
|
181
|
+
if (!!device) return [3 /*break*/, 4];
|
|
170
182
|
return [4 /*yield*/, bleManagerInstance().connectedDevices((0, devices_1.getBluetoothServiceUuids)())];
|
|
171
|
-
case
|
|
183
|
+
case 3:
|
|
172
184
|
connectedDevices = _g.sent();
|
|
173
185
|
connectedDevicesFiltered = connectedDevices.filter(function (d) { return d.id === deviceOrId; });
|
|
174
|
-
(0, logs_1.log)(
|
|
186
|
+
(0, logs_1.log)(TAG, "found ".concat(connectedDevicesFiltered.length, " connected devices"));
|
|
175
187
|
_d = __read(connectedDevicesFiltered, 1), device = _d[0];
|
|
188
|
+
_g.label = 4;
|
|
189
|
+
case 4:
|
|
190
|
+
if (!!device) return [3 /*break*/, 11];
|
|
191
|
+
// We still don't have a device, so we attempt to connect to it.
|
|
192
|
+
(0, logs_1.log)(TAG, "connectToDevice(".concat(deviceOrId, ")"));
|
|
176
193
|
_g.label = 5;
|
|
177
194
|
case 5:
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
_g.label = 6;
|
|
195
|
+
_g.trys.push([5, 7, , 11]);
|
|
196
|
+
return [4 /*yield*/, bleManagerInstance().connectToDevice(deviceOrId)];
|
|
181
197
|
case 6:
|
|
182
|
-
_g.trys.push([6, 8, , 12]);
|
|
183
|
-
return [4 /*yield*/, bleManagerInstance().connectToDevice(deviceOrId, connectOptions)];
|
|
184
|
-
case 7:
|
|
185
198
|
device = _g.sent();
|
|
186
|
-
return [3 /*break*/,
|
|
187
|
-
case
|
|
199
|
+
return [3 /*break*/, 11];
|
|
200
|
+
case 7:
|
|
188
201
|
e_1 = _g.sent();
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
connectOptions = {};
|
|
202
|
+
(0, logs_1.log)(TAG, "error code ".concat(e_1.errorCode));
|
|
203
|
+
if (!(e_1.errorCode === react_native_ble_plx_1.BleErrorCode.DeviceMTUChangeFailed)) return [3 /*break*/, 9];
|
|
192
204
|
return [4 /*yield*/, bleManagerInstance().connectToDevice(deviceOrId)];
|
|
193
|
-
case
|
|
205
|
+
case 8:
|
|
194
206
|
device = _g.sent();
|
|
195
|
-
return [3 /*break*/,
|
|
196
|
-
case
|
|
197
|
-
case
|
|
198
|
-
case
|
|
207
|
+
return [3 /*break*/, 10];
|
|
208
|
+
case 9: throw e_1;
|
|
209
|
+
case 10: return [3 /*break*/, 11];
|
|
210
|
+
case 11:
|
|
199
211
|
if (!device) {
|
|
200
212
|
throw new errors_1.CantOpenDevice();
|
|
201
213
|
}
|
|
202
|
-
return [3 /*break*/,
|
|
203
|
-
case
|
|
214
|
+
return [3 /*break*/, 13];
|
|
215
|
+
case 12:
|
|
216
|
+
// It was already a Device
|
|
204
217
|
device = deviceOrId;
|
|
205
|
-
_g.label =
|
|
206
|
-
case
|
|
218
|
+
_g.label = 13;
|
|
219
|
+
case 13: return [4 /*yield*/, device.isConnected()];
|
|
220
|
+
case 14:
|
|
221
|
+
if (!!(_g.sent())) return [3 /*break*/, 21];
|
|
222
|
+
(0, logs_1.log)(TAG, "not connected. connecting...");
|
|
223
|
+
_g.label = 15;
|
|
207
224
|
case 15:
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
_g.label = 16;
|
|
225
|
+
_g.trys.push([15, 17, , 21]);
|
|
226
|
+
return [4 /*yield*/, device.connect()];
|
|
211
227
|
case 16:
|
|
212
|
-
_g.trys.push([16, 18, , 22]);
|
|
213
|
-
return [4 /*yield*/, device.connect(connectOptions)];
|
|
214
|
-
case 17:
|
|
215
228
|
_g.sent();
|
|
216
|
-
return [3 /*break*/,
|
|
217
|
-
case
|
|
229
|
+
return [3 /*break*/, 21];
|
|
230
|
+
case 17:
|
|
218
231
|
e_2 = _g.sent();
|
|
219
|
-
if (!(e_2.errorCode === react_native_ble_plx_1.BleErrorCode.DeviceMTUChangeFailed)) return [3 /*break*/,
|
|
220
|
-
//
|
|
221
|
-
connectOptions = {};
|
|
232
|
+
if (!(e_2.errorCode === react_native_ble_plx_1.BleErrorCode.DeviceMTUChangeFailed)) return [3 /*break*/, 19];
|
|
233
|
+
// Retry once for this specific error.
|
|
222
234
|
return [4 /*yield*/, device.connect()];
|
|
223
|
-
case
|
|
235
|
+
case 18:
|
|
236
|
+
// Retry once for this specific error.
|
|
224
237
|
_g.sent();
|
|
225
|
-
return [3 /*break*/,
|
|
226
|
-
case
|
|
227
|
-
case
|
|
228
|
-
case
|
|
229
|
-
case
|
|
238
|
+
return [3 /*break*/, 20];
|
|
239
|
+
case 19: throw e_2;
|
|
240
|
+
case 20: return [3 /*break*/, 21];
|
|
241
|
+
case 21: return [4 /*yield*/, device.discoverAllServicesAndCharacteristics()];
|
|
242
|
+
case 22:
|
|
230
243
|
_g.sent();
|
|
231
244
|
res = retrieveInfos(device);
|
|
232
|
-
if (!!res) return [3 /*break*/,
|
|
245
|
+
if (!!res) return [3 /*break*/, 32];
|
|
246
|
+
_g.label = 23;
|
|
247
|
+
case 23:
|
|
248
|
+
_g.trys.push([23, 30, 31, 32]);
|
|
249
|
+
_a = __values((0, devices_1.getBluetoothServiceUuids)()), _b = _a.next();
|
|
233
250
|
_g.label = 24;
|
|
234
251
|
case 24:
|
|
235
|
-
|
|
236
|
-
|
|
252
|
+
if (!!_b.done) return [3 /*break*/, 29];
|
|
253
|
+
uuid = _b.value;
|
|
237
254
|
_g.label = 25;
|
|
238
255
|
case 25:
|
|
239
|
-
|
|
240
|
-
uuid = _b.value;
|
|
241
|
-
_g.label = 26;
|
|
242
|
-
case 26:
|
|
243
|
-
_g.trys.push([26, 28, , 29]);
|
|
256
|
+
_g.trys.push([25, 27, , 28]);
|
|
244
257
|
return [4 /*yield*/, device.characteristicsForService(uuid)];
|
|
245
|
-
case
|
|
258
|
+
case 26:
|
|
246
259
|
characteristics = _g.sent();
|
|
247
260
|
res = (0, devices_1.getInfosForServiceUuid)(uuid);
|
|
248
|
-
return [3 /*break*/, 30];
|
|
249
|
-
case 28:
|
|
250
|
-
e_3 = _g.sent();
|
|
251
261
|
return [3 /*break*/, 29];
|
|
252
|
-
case
|
|
262
|
+
case 27:
|
|
263
|
+
e_3 = _g.sent();
|
|
264
|
+
return [3 /*break*/, 28];
|
|
265
|
+
case 28:
|
|
253
266
|
_b = _a.next();
|
|
254
|
-
return [3 /*break*/,
|
|
255
|
-
case
|
|
256
|
-
case
|
|
267
|
+
return [3 /*break*/, 24];
|
|
268
|
+
case 29: return [3 /*break*/, 32];
|
|
269
|
+
case 30:
|
|
257
270
|
e_4_1 = _g.sent();
|
|
258
271
|
e_4 = { error: e_4_1 };
|
|
259
|
-
return [3 /*break*/,
|
|
260
|
-
case
|
|
272
|
+
return [3 /*break*/, 32];
|
|
273
|
+
case 31:
|
|
261
274
|
try {
|
|
262
275
|
if (_b && !_b.done && (_e = _a["return"])) _e.call(_a);
|
|
263
276
|
}
|
|
264
277
|
finally { if (e_4) throw e_4.error; }
|
|
265
278
|
return [7 /*endfinally*/];
|
|
266
|
-
case
|
|
279
|
+
case 32:
|
|
267
280
|
if (!res) {
|
|
268
281
|
throw new errors_1.TransportError("service not found", "BLEServiceNotFound");
|
|
269
282
|
}
|
|
270
283
|
deviceModel = res.deviceModel, serviceUuid = res.serviceUuid, writeUuid = res.writeUuid, writeCmdUuid = res.writeCmdUuid, notifyUuid = res.notifyUuid;
|
|
271
|
-
if (!!characteristics) return [3 /*break*/,
|
|
284
|
+
if (!!characteristics) return [3 /*break*/, 34];
|
|
272
285
|
return [4 /*yield*/, device.characteristicsForService(serviceUuid)];
|
|
273
|
-
case
|
|
286
|
+
case 33:
|
|
274
287
|
characteristics = _g.sent();
|
|
275
|
-
_g.label =
|
|
276
|
-
case
|
|
288
|
+
_g.label = 34;
|
|
289
|
+
case 34:
|
|
277
290
|
if (!characteristics) {
|
|
278
291
|
throw new errors_1.TransportError("service not found", "BLEServiceNotFound");
|
|
279
292
|
}
|
|
@@ -299,23 +312,23 @@ function open(deviceOrId, needsReconnect) {
|
|
|
299
312
|
finally { if (e_5) throw e_5.error; }
|
|
300
313
|
}
|
|
301
314
|
if (!writeC) {
|
|
302
|
-
throw new errors_1.TransportError("write characteristic not found", "
|
|
315
|
+
throw new errors_1.TransportError("write characteristic not found", "BLECharacteristicNotFound");
|
|
303
316
|
}
|
|
304
317
|
if (!notifyC) {
|
|
305
|
-
throw new errors_1.TransportError("notify characteristic not found", "
|
|
318
|
+
throw new errors_1.TransportError("notify characteristic not found", "BLECharacteristicNotFound");
|
|
306
319
|
}
|
|
307
320
|
if (!writeC.isWritableWithResponse) {
|
|
308
|
-
throw new errors_1.TransportError("write characteristic not writableWithResponse", "
|
|
321
|
+
throw new errors_1.TransportError("write characteristic not writableWithResponse", "BLECharacteristicInvalid");
|
|
309
322
|
}
|
|
310
323
|
if (!notifyC.isNotifiable) {
|
|
311
|
-
throw new errors_1.TransportError("notify characteristic not notifiable", "
|
|
324
|
+
throw new errors_1.TransportError("notify characteristic not notifiable", "BLECharacteristicInvalid");
|
|
312
325
|
}
|
|
313
326
|
if (writeCmdC) {
|
|
314
327
|
if (!writeCmdC.isWritableWithoutResponse) {
|
|
315
|
-
throw new errors_1.TransportError("write cmd characteristic not writableWithoutResponse", "
|
|
328
|
+
throw new errors_1.TransportError("write cmd characteristic not writableWithoutResponse", "BLECharacteristicInvalid");
|
|
316
329
|
}
|
|
317
330
|
}
|
|
318
|
-
(0, logs_1.log)(
|
|
331
|
+
(0, logs_1.log)(TAG, "device.mtu=".concat(device.mtu));
|
|
319
332
|
notifyObservable = (0, monitorCharacteristic_1.monitorCharacteristic)(notifyC).pipe((0, operators_1.catchError)(function (e) {
|
|
320
333
|
// LL-9033 fw 2.0.2 introduced this case, we silence the inner unhandled error.
|
|
321
334
|
var msg = String(e);
|
|
@@ -328,58 +341,57 @@ function open(deviceOrId, needsReconnect) {
|
|
|
328
341
|
(0, logs_1.log)("ble-frame", "<= " + value.toString("hex"));
|
|
329
342
|
}), (0, operators_1.share)());
|
|
330
343
|
notif = notifyObservable.subscribe();
|
|
331
|
-
transport = new
|
|
332
|
-
return [4 /*yield*/, transport.requestConnectionPriority("High")];
|
|
333
|
-
case 36:
|
|
334
|
-
_g.sent();
|
|
344
|
+
transport = new BleTransport(device, writeC, writeCmdC, notifyObservable, deviceModel);
|
|
335
345
|
onDisconnect = function (e) {
|
|
346
|
+
transport.isConnected = false;
|
|
336
347
|
transport.notYetDisconnected = false;
|
|
337
348
|
notif.unsubscribe();
|
|
338
|
-
disconnectedSub.remove();
|
|
349
|
+
disconnectedSub === null || disconnectedSub === void 0 ? void 0 : disconnectedSub.remove();
|
|
350
|
+
clearDisconnectTimeout(transport.id);
|
|
339
351
|
delete transportsCache[transport.id];
|
|
340
|
-
(0, logs_1.log)(
|
|
352
|
+
(0, logs_1.log)(TAG, "BleTransport(".concat(transport.id, ") disconnected"));
|
|
341
353
|
transport.emit("disconnect", e);
|
|
342
354
|
};
|
|
343
355
|
// eslint-disable-next-line require-atomic-updates
|
|
344
356
|
transportsCache[transport.id] = transport;
|
|
357
|
+
beforeMTUTime = Date.now();
|
|
345
358
|
disconnectedSub = device.onDisconnected(function (e) {
|
|
346
359
|
if (!transport.notYetDisconnected)
|
|
347
360
|
return;
|
|
348
361
|
onDisconnect(e);
|
|
349
362
|
});
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
_g.trys.push([37, , 39, 45]);
|
|
363
|
+
_g.label = 35;
|
|
364
|
+
case 35:
|
|
365
|
+
_g.trys.push([35, , 37, 43]);
|
|
354
366
|
return [4 /*yield*/, transport.inferMTU()];
|
|
355
|
-
case
|
|
367
|
+
case 36:
|
|
356
368
|
_g.sent();
|
|
357
|
-
return [3 /*break*/,
|
|
358
|
-
case
|
|
369
|
+
return [3 /*break*/, 43];
|
|
370
|
+
case 37:
|
|
359
371
|
afterMTUTime = Date.now();
|
|
360
|
-
if (!reconnectionConfig) return [3 /*break*/,
|
|
372
|
+
if (!reconnectionConfig) return [3 /*break*/, 41];
|
|
361
373
|
// workaround for #279: we need to open() again if we come the first time here,
|
|
362
374
|
// to make sure we do a disconnect() after the first pairing time
|
|
363
375
|
// because of a firmware bug
|
|
364
376
|
if (afterMTUTime - beforeMTUTime < reconnectionConfig.pairingThreshold) {
|
|
365
377
|
needsReconnect = false; // (optim) there is likely no new pairing done because mtu answer was fast.
|
|
366
378
|
}
|
|
367
|
-
if (!needsReconnect) return [3 /*break*/,
|
|
379
|
+
if (!needsReconnect) return [3 /*break*/, 40];
|
|
368
380
|
// necessary time for the bonding workaround
|
|
369
|
-
return [4 /*yield*/,
|
|
370
|
-
case
|
|
381
|
+
return [4 /*yield*/, BleTransport.disconnect(transport.id)["catch"](function () { })];
|
|
382
|
+
case 38:
|
|
371
383
|
// necessary time for the bonding workaround
|
|
372
384
|
_g.sent();
|
|
373
385
|
return [4 /*yield*/, delay(reconnectionConfig.delayAfterFirstPairing)];
|
|
374
|
-
case
|
|
386
|
+
case 39:
|
|
375
387
|
_g.sent();
|
|
388
|
+
_g.label = 40;
|
|
389
|
+
case 40: return [3 /*break*/, 42];
|
|
390
|
+
case 41:
|
|
391
|
+
needsReconnect = false;
|
|
376
392
|
_g.label = 42;
|
|
377
|
-
case 42: return [
|
|
393
|
+
case 42: return [7 /*endfinally*/];
|
|
378
394
|
case 43:
|
|
379
|
-
needsReconnect = false;
|
|
380
|
-
_g.label = 44;
|
|
381
|
-
case 44: return [7 /*endfinally*/];
|
|
382
|
-
case 45:
|
|
383
395
|
if (needsReconnect) {
|
|
384
396
|
return [2 /*return*/, open(device, false)];
|
|
385
397
|
}
|
|
@@ -391,16 +403,22 @@ function open(deviceOrId, needsReconnect) {
|
|
|
391
403
|
/**
|
|
392
404
|
* react-native bluetooth BLE implementation
|
|
393
405
|
* @example
|
|
394
|
-
* import
|
|
406
|
+
* import BleTransport from "@ledgerhq/react-native-hw-transport-ble";
|
|
395
407
|
*/
|
|
396
|
-
var
|
|
397
|
-
|
|
398
|
-
|
|
408
|
+
var TAG = "ble-verbose";
|
|
409
|
+
var BleTransport = /** @class */ (function (_super) {
|
|
410
|
+
__extends(BleTransport, _super);
|
|
411
|
+
function BleTransport(device, writeCharacteristic, writeCmdCharacteristic, notifyObservable, deviceModel) {
|
|
399
412
|
var _this = _super.call(this) || this;
|
|
413
|
+
_this.disconnectTimeout = null;
|
|
414
|
+
_this.isConnected = true;
|
|
400
415
|
_this.mtuSize = 20;
|
|
401
416
|
_this.notYetDisconnected = true;
|
|
402
417
|
/**
|
|
403
|
-
*
|
|
418
|
+
* Send data to the device using a low level API.
|
|
419
|
+
* It's recommended to use the "send" method for a higher level API.
|
|
420
|
+
* @param {Buffer} apdu - The data to send.
|
|
421
|
+
* @returns {Promise<Buffer>} A promise that resolves with the response data from the device.
|
|
404
422
|
*/
|
|
405
423
|
_this.exchange = function (apdu) {
|
|
406
424
|
return _this.exchangeAtomicImpl(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
@@ -411,9 +429,7 @@ var BluetoothTransport = /** @class */ (function (_super) {
|
|
|
411
429
|
_b.trys.push([0, 2, , 5]);
|
|
412
430
|
msgIn = apdu.toString("hex");
|
|
413
431
|
(0, logs_1.log)("apdu", "=> ".concat(msgIn));
|
|
414
|
-
return [4 /*yield*/, (0, rxjs_1.merge)(
|
|
415
|
-
// $FlowFixMe
|
|
416
|
-
this.notifyObservable.pipe(receiveAPDU_1.receiveAPDU), (0, sendAPDU_1.sendAPDU)(this.write, apdu, this.mtuSize)).toPromise()];
|
|
432
|
+
return [4 /*yield*/, (0, rxjs_1.merge)(this.notifyObservable.pipe(receiveAPDU_1.receiveAPDU), (0, sendAPDU_1.sendAPDU)(this.write, apdu, this.mtuSize)).toPromise()];
|
|
417
433
|
case 1:
|
|
418
434
|
data = _b.sent();
|
|
419
435
|
msgOut = data.toString("hex");
|
|
@@ -436,6 +452,12 @@ var BluetoothTransport = /** @class */ (function (_super) {
|
|
|
436
452
|
});
|
|
437
453
|
}); });
|
|
438
454
|
};
|
|
455
|
+
/**
|
|
456
|
+
* Do not call this directly unless you know what you're doing. Communication
|
|
457
|
+
* with a Ledger device should be through the {@link exchange} method.
|
|
458
|
+
* @param buffer
|
|
459
|
+
* @param txid
|
|
460
|
+
*/
|
|
439
461
|
_this.write = function (buffer, txid) { return __awaiter(_this, void 0, void 0, function () {
|
|
440
462
|
var e_7, e_8;
|
|
441
463
|
return __generator(this, function (_b) {
|
|
@@ -473,15 +495,17 @@ var BluetoothTransport = /** @class */ (function (_super) {
|
|
|
473
495
|
_this.writeCmdCharacteristic = writeCmdCharacteristic;
|
|
474
496
|
_this.notifyObservable = notifyObservable;
|
|
475
497
|
_this.deviceModel = deviceModel;
|
|
476
|
-
(0, logs_1.log)(
|
|
498
|
+
(0, logs_1.log)(TAG, "BleTransport(".concat(String(_this.id), ") new instance"));
|
|
499
|
+
clearDisconnectTimeout(_this.id);
|
|
477
500
|
return _this;
|
|
478
501
|
}
|
|
479
502
|
/**
|
|
480
|
-
*
|
|
481
|
-
*
|
|
482
|
-
*
|
|
503
|
+
* Listen to state changes on the bleManagerInstance and notify the
|
|
504
|
+
* specified observer.
|
|
505
|
+
* @param observer
|
|
506
|
+
* @returns TransportSubscription
|
|
483
507
|
*/
|
|
484
|
-
|
|
508
|
+
BleTransport.observeState = function (observer) {
|
|
485
509
|
var emitFromState = function (type) {
|
|
486
510
|
observer.next({
|
|
487
511
|
type: type,
|
|
@@ -495,48 +519,52 @@ var BluetoothTransport = /** @class */ (function (_super) {
|
|
|
495
519
|
};
|
|
496
520
|
/**
|
|
497
521
|
* Scan for bluetooth Ledger devices
|
|
522
|
+
* @param observer Device is partial in order to avoid the live-common/this dep
|
|
523
|
+
* @returns TransportSubscription
|
|
498
524
|
*/
|
|
499
|
-
|
|
525
|
+
BleTransport.listen = function (observer) {
|
|
500
526
|
var _this = this;
|
|
501
|
-
(0, logs_1.log)(
|
|
527
|
+
(0, logs_1.log)(TAG, "listening for devices");
|
|
502
528
|
var unsubscribed;
|
|
503
529
|
var stateSub = bleManagerInstance().onStateChange(function (state) { return __awaiter(_this, void 0, void 0, function () {
|
|
504
530
|
var devices;
|
|
505
531
|
return __generator(this, function (_b) {
|
|
506
532
|
switch (_b.label) {
|
|
507
533
|
case 0:
|
|
508
|
-
if (!(state === "PoweredOn")) return [3 /*break*/,
|
|
534
|
+
if (!(state === "PoweredOn")) return [3 /*break*/, 4];
|
|
509
535
|
stateSub.remove();
|
|
510
536
|
return [4 /*yield*/, bleManagerInstance().connectedDevices((0, devices_1.getBluetoothServiceUuids)())];
|
|
511
537
|
case 1:
|
|
512
538
|
devices = _b.sent();
|
|
513
539
|
if (unsubscribed)
|
|
514
540
|
return [2 /*return*/];
|
|
515
|
-
return [
|
|
516
|
-
|
|
517
|
-
|
|
541
|
+
if (!devices.length) return [3 /*break*/, 3];
|
|
542
|
+
(0, logs_1.log)(TAG, "disconnecting from devices");
|
|
543
|
+
return [4 /*yield*/, Promise.all(devices.map(function (d) { return BleTransport.disconnect(d.id)["catch"](function () { }); }))];
|
|
518
544
|
case 2:
|
|
519
545
|
_b.sent();
|
|
546
|
+
_b.label = 3;
|
|
547
|
+
case 3:
|
|
520
548
|
if (unsubscribed)
|
|
521
549
|
return [2 /*return*/];
|
|
522
|
-
bleManagerInstance().startDeviceScan((0, devices_1.getBluetoothServiceUuids)(), null, function (bleError,
|
|
550
|
+
bleManagerInstance().startDeviceScan((0, devices_1.getBluetoothServiceUuids)(), null, function (bleError, scannedDevice) {
|
|
523
551
|
if (bleError) {
|
|
524
|
-
observer.error(mapBleErrorToHwTransportError(bleError));
|
|
552
|
+
observer.error((0, remapErrors_1.mapBleErrorToHwTransportError)(bleError));
|
|
525
553
|
unsubscribe();
|
|
526
554
|
return;
|
|
527
555
|
}
|
|
528
|
-
var res = retrieveInfos(
|
|
556
|
+
var res = retrieveInfos(scannedDevice);
|
|
529
557
|
var deviceModel = res && res.deviceModel;
|
|
530
|
-
if (
|
|
558
|
+
if (scannedDevice) {
|
|
531
559
|
observer.next({
|
|
532
560
|
type: "add",
|
|
533
|
-
descriptor:
|
|
561
|
+
descriptor: scannedDevice,
|
|
534
562
|
deviceModel: deviceModel
|
|
535
563
|
});
|
|
536
564
|
}
|
|
537
565
|
});
|
|
538
|
-
_b.label =
|
|
539
|
-
case
|
|
566
|
+
_b.label = 4;
|
|
567
|
+
case 4: return [2 /*return*/];
|
|
540
568
|
}
|
|
541
569
|
});
|
|
542
570
|
}); }, true);
|
|
@@ -544,7 +572,7 @@ var BluetoothTransport = /** @class */ (function (_super) {
|
|
|
544
572
|
unsubscribed = true;
|
|
545
573
|
bleManagerInstance().stopDeviceScan();
|
|
546
574
|
stateSub.remove();
|
|
547
|
-
(0, logs_1.log)(
|
|
575
|
+
(0, logs_1.log)(TAG, "done listening.");
|
|
548
576
|
};
|
|
549
577
|
return {
|
|
550
578
|
unsubscribe: unsubscribe
|
|
@@ -552,17 +580,20 @@ var BluetoothTransport = /** @class */ (function (_super) {
|
|
|
552
580
|
};
|
|
553
581
|
/**
|
|
554
582
|
* Open a BLE transport
|
|
555
|
-
* @param {
|
|
583
|
+
* @param {Device | string} deviceOrId
|
|
556
584
|
*/
|
|
557
|
-
|
|
585
|
+
BleTransport.open = function (deviceOrId) {
|
|
558
586
|
return __awaiter(this, void 0, void 0, function () {
|
|
559
587
|
return __generator(this, function (_b) {
|
|
560
588
|
return [2 /*return*/, open(deviceOrId, true)];
|
|
561
589
|
});
|
|
562
590
|
});
|
|
563
591
|
};
|
|
564
|
-
|
|
565
|
-
|
|
592
|
+
/**
|
|
593
|
+
* Negotiate with the device the maximum transfer unit for the ble frames
|
|
594
|
+
* @returns Promise<number>
|
|
595
|
+
*/
|
|
596
|
+
BleTransport.prototype.inferMTU = function () {
|
|
566
597
|
return __awaiter(this, void 0, void 0, function () {
|
|
567
598
|
var mtu, mtuSize;
|
|
568
599
|
var _this = this;
|
|
@@ -587,7 +618,7 @@ var BluetoothTransport = /** @class */ (function (_super) {
|
|
|
587
618
|
return [3 /*break*/, 4];
|
|
588
619
|
case 2:
|
|
589
620
|
e_9 = _b.sent();
|
|
590
|
-
(0, logs_1.log)("ble-error", "inferMTU got " +
|
|
621
|
+
(0, logs_1.log)("ble-error", "inferMTU got " + JSON.stringify(e_9));
|
|
591
622
|
return [4 /*yield*/, bleManagerInstance()
|
|
592
623
|
.cancelDeviceConnection(this.id)["catch"](function () { })];
|
|
593
624
|
case 3:
|
|
@@ -601,7 +632,7 @@ var BluetoothTransport = /** @class */ (function (_super) {
|
|
|
601
632
|
_b.sent();
|
|
602
633
|
if (mtu > 23) {
|
|
603
634
|
mtuSize = mtu - 3;
|
|
604
|
-
(0, logs_1.log)(
|
|
635
|
+
(0, logs_1.log)(TAG, "BleTransport(".concat(this.id, ") mtu set to ").concat(mtuSize));
|
|
605
636
|
this.mtuSize = mtuSize;
|
|
606
637
|
}
|
|
607
638
|
return [2 /*return*/, this.mtuSize];
|
|
@@ -609,84 +640,112 @@ var BluetoothTransport = /** @class */ (function (_super) {
|
|
|
609
640
|
});
|
|
610
641
|
});
|
|
611
642
|
};
|
|
612
|
-
|
|
643
|
+
/**
|
|
644
|
+
* Exposed method from the ble-plx library
|
|
645
|
+
* Request the connection priority for the given device.
|
|
646
|
+
* @param {"Balanced" | "High" | "LowPower"} connectionPriority: Connection priority.
|
|
647
|
+
* @returns {Promise<Device>} Connected device.
|
|
648
|
+
*/
|
|
649
|
+
BleTransport.prototype.requestConnectionPriority = function (connectionPriority) {
|
|
613
650
|
return __awaiter(this, void 0, void 0, function () {
|
|
614
651
|
return __generator(this, function (_b) {
|
|
615
652
|
switch (_b.label) {
|
|
616
653
|
case 0: return [4 /*yield*/, (0, remapErrors_1.decoratePromiseErrors)(this.device.requestConnectionPriority(react_native_ble_plx_1.ConnectionPriority[connectionPriority]))];
|
|
617
|
-
case 1:
|
|
618
|
-
_b.sent();
|
|
619
|
-
return [2 /*return*/];
|
|
654
|
+
case 1: return [2 /*return*/, _b.sent()];
|
|
620
655
|
}
|
|
621
656
|
});
|
|
622
657
|
});
|
|
623
658
|
};
|
|
624
|
-
|
|
625
|
-
|
|
659
|
+
/**
|
|
660
|
+
* We intentionally do not immediately close a transport connection.
|
|
661
|
+
* Instead, we queue the disconnect and wait for a future connection to dismiss the event.
|
|
662
|
+
* This approach prevents unnecessary disconnects and reconnects. We use the isConnected
|
|
663
|
+
* flag to ensure that we do not trigger a disconnect if the current cached transport has
|
|
664
|
+
* already been disconnected.
|
|
665
|
+
* @returns {Promise<void>}
|
|
666
|
+
*/
|
|
667
|
+
BleTransport.prototype.close = function () {
|
|
626
668
|
return __awaiter(this, void 0, void 0, function () {
|
|
669
|
+
var resolve, disconnectPromise;
|
|
670
|
+
var _this = this;
|
|
627
671
|
return __generator(this, function (_b) {
|
|
628
672
|
switch (_b.label) {
|
|
629
673
|
case 0:
|
|
630
|
-
|
|
631
|
-
|
|
674
|
+
disconnectPromise = new Promise(function (innerResolve) {
|
|
675
|
+
resolve = innerResolve;
|
|
676
|
+
});
|
|
677
|
+
clearDisconnectTimeout(this.id);
|
|
678
|
+
(0, logs_1.log)(TAG, "Queuing a disconnect");
|
|
679
|
+
this.disconnectTimeout = setTimeout(function () {
|
|
680
|
+
(0, logs_1.log)(TAG, "Triggering a disconnect from ".concat(_this.id));
|
|
681
|
+
if (_this.isConnected) {
|
|
682
|
+
BleTransport.disconnect(_this.id)["catch"](function () { })["finally"](resolve);
|
|
683
|
+
}
|
|
684
|
+
else {
|
|
685
|
+
resolve();
|
|
686
|
+
}
|
|
687
|
+
}, BleTransport.disconnectTimeoutMs);
|
|
688
|
+
// The closure will occur no later than 5s, triggered either by disconnection
|
|
689
|
+
// or the actual response of the apdu.
|
|
690
|
+
return [4 /*yield*/, Promise.race([
|
|
691
|
+
this.exchangeBusyPromise || Promise.resolve(),
|
|
692
|
+
disconnectPromise,
|
|
693
|
+
])];
|
|
632
694
|
case 1:
|
|
695
|
+
// The closure will occur no later than 5s, triggered either by disconnection
|
|
696
|
+
// or the actual response of the apdu.
|
|
633
697
|
_b.sent();
|
|
634
|
-
|
|
635
|
-
case 2: return [2 /*return*/];
|
|
698
|
+
return [2 /*return*/];
|
|
636
699
|
}
|
|
637
700
|
});
|
|
638
701
|
});
|
|
639
702
|
};
|
|
640
703
|
var _a;
|
|
641
|
-
_a =
|
|
704
|
+
_a = BleTransport;
|
|
705
|
+
BleTransport.disconnectTimeoutMs = 5000;
|
|
642
706
|
/**
|
|
643
707
|
*
|
|
644
708
|
*/
|
|
645
|
-
|
|
709
|
+
BleTransport.isSupported = function () {
|
|
646
710
|
return Promise.resolve(typeof react_native_ble_plx_1.BleManager === "function");
|
|
647
711
|
};
|
|
648
712
|
/**
|
|
649
713
|
*
|
|
650
714
|
*/
|
|
651
|
-
|
|
652
|
-
bleManagerInstance().setLogLevel(level);
|
|
653
|
-
};
|
|
654
|
-
BluetoothTransport.list = function () {
|
|
715
|
+
BleTransport.list = function () {
|
|
655
716
|
throw new Error("not implemented");
|
|
656
717
|
};
|
|
657
718
|
/**
|
|
658
|
-
*
|
|
719
|
+
* Exposed method from the ble-plx library
|
|
720
|
+
* Sets new log level for native module's logging mechanism.
|
|
721
|
+
* @param string logLevel New log level to be set.
|
|
659
722
|
*/
|
|
660
|
-
|
|
723
|
+
BleTransport.setLogLevel = function (logLevel) {
|
|
724
|
+
if (Object.values(react_native_ble_plx_1.LogLevel).includes(logLevel)) {
|
|
725
|
+
bleManagerInstance().setLogLevel(logLevel);
|
|
726
|
+
}
|
|
727
|
+
else {
|
|
728
|
+
throw new Error("".concat(logLevel, " is not a valid LogLevel"));
|
|
729
|
+
}
|
|
730
|
+
};
|
|
731
|
+
/**
|
|
732
|
+
* Exposed method from the ble-plx library
|
|
733
|
+
* Disconnects from {@link Device} if it's connected or cancels pending connection.
|
|
734
|
+
*/
|
|
735
|
+
BleTransport.disconnect = function (id) { return __awaiter(void 0, void 0, void 0, function () {
|
|
661
736
|
return __generator(_a, function (_b) {
|
|
662
737
|
switch (_b.label) {
|
|
663
738
|
case 0:
|
|
664
|
-
(0, logs_1.log)(
|
|
739
|
+
(0, logs_1.log)(TAG, "user disconnect(".concat(id, ")"));
|
|
665
740
|
return [4 /*yield*/, bleManagerInstance().cancelDeviceConnection(id)];
|
|
666
741
|
case 1:
|
|
667
742
|
_b.sent();
|
|
743
|
+
(0, logs_1.log)(TAG, "disconnected");
|
|
668
744
|
return [2 /*return*/];
|
|
669
745
|
}
|
|
670
746
|
});
|
|
671
747
|
}); };
|
|
672
|
-
return
|
|
748
|
+
return BleTransport;
|
|
673
749
|
}(hw_transport_1["default"]));
|
|
674
|
-
exports["default"] =
|
|
675
|
-
var bleErrorToHwTransportError = new Map([
|
|
676
|
-
[react_native_ble_plx_1.BleErrorCode.ScanStartFailed, errors_1.HwTransportErrorType.BleScanStartFailed],
|
|
677
|
-
[
|
|
678
|
-
react_native_ble_plx_1.BleErrorCode.LocationServicesDisabled,
|
|
679
|
-
errors_1.HwTransportErrorType.BleLocationServicesDisabled,
|
|
680
|
-
],
|
|
681
|
-
[
|
|
682
|
-
react_native_ble_plx_1.BleErrorCode.BluetoothUnauthorized,
|
|
683
|
-
errors_1.HwTransportErrorType.BleBluetoothUnauthorized,
|
|
684
|
-
],
|
|
685
|
-
]);
|
|
686
|
-
var mapBleErrorToHwTransportError = function (bleError) {
|
|
687
|
-
var message = "".concat(bleError.message, ". Origin: ").concat(bleError.errorCode);
|
|
688
|
-
var inferedType = bleErrorToHwTransportError.get(bleError.errorCode);
|
|
689
|
-
var type = !inferedType ? errors_1.HwTransportErrorType.Unknown : inferedType;
|
|
690
|
-
return new errors_1.HwTransportError(type, message);
|
|
691
|
-
};
|
|
750
|
+
exports["default"] = BleTransport;
|
|
692
751
|
//# sourceMappingURL=BleTransport.js.map
|