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