@ledgerhq/react-native-hw-transport-ble 6.29.5 → 6.29.6-nightly.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.
@@ -4,15 +4,20 @@ exports.monitorCharacteristic = void 0;
4
4
  const rxjs_1 = require("rxjs");
5
5
  const errors_1 = require("@ledgerhq/errors");
6
6
  const logs_1 = require("@ledgerhq/logs");
7
- const monitorCharacteristic = (characteristic) => new rxjs_1.Observable(o => {
8
- (0, logs_1.log)("ble-verbose", "start monitor " + characteristic.uuid);
7
+ const LOG_TYPE = "ble-verbose";
8
+ const monitorCharacteristic = (characteristic, context) => new rxjs_1.Observable(o => {
9
+ const tracer = new logs_1.LocalTracer(LOG_TYPE, context);
10
+ tracer.trace(`Start monitoring BLE characteristics`, {
11
+ characteristicUuid: characteristic.uuid,
12
+ });
9
13
  const subscription = characteristic.monitor((error, c) => {
10
14
  if (error) {
11
- (0, logs_1.log)("ble-verbose", "error monitor " + characteristic.uuid + ": " + error);
15
+ tracer.trace("Error while monitoring characteristics", { error });
12
16
  o.error(error);
13
17
  }
14
18
  else if (!c) {
15
- o.error(new errors_1.TransportError("characteristic monitor null value", "CharacteristicMonitorNull"));
19
+ tracer.trace("BLE monitored characteristic null value");
20
+ o.error(new errors_1.TransportError("Characteristic monitor null value", "CharacteristicMonitorNull"));
16
21
  }
17
22
  else {
18
23
  try {
@@ -25,7 +30,6 @@ const monitorCharacteristic = (characteristic) => new rxjs_1.Observable(o => {
25
30
  }
26
31
  });
27
32
  return () => {
28
- (0, logs_1.log)("ble-verbose", "end monitor " + characteristic.uuid);
29
33
  subscription.remove();
30
34
  };
31
35
  });
@@ -1 +1 @@
1
- {"version":3,"file":"monitorCharacteristic.js","sourceRoot":"","sources":["../src/monitorCharacteristic.ts"],"names":[],"mappings":";;;AAAA,+BAAkC;AAClC,6CAAkD;AAElD,yCAAqC;AAC9B,MAAM,qBAAqB,GAAG,CAAC,cAA8B,EAAsB,EAAE,CAC1F,IAAI,iBAAU,CAAC,CAAC,CAAC,EAAE;IACjB,IAAA,UAAG,EAAC,aAAa,EAAE,gBAAgB,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IAC3D,MAAM,YAAY,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;QACvD,IAAI,KAAK,EAAE;YACT,IAAA,UAAG,EAAC,aAAa,EAAE,gBAAgB,GAAG,cAAc,CAAC,IAAI,GAAG,IAAI,GAAG,KAAK,CAAC,CAAC;YAC1E,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;SAChB;aAAM,IAAI,CAAC,CAAC,EAAE;YACb,CAAC,CAAC,KAAK,CACL,IAAI,uBAAc,CAAC,mCAAmC,EAAE,2BAA2B,CAAC,CACrF,CAAC;SACH;aAAM;YACL,IAAI;gBACF,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;gBAC7C,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;aACf;YAAC,OAAO,KAAK,EAAE;gBACd,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;aAChB;SACF;IACH,CAAC,CAAC,CAAC;IACH,OAAO,GAAG,EAAE;QACV,IAAA,UAAG,EAAC,aAAa,EAAE,cAAc,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;QACzD,YAAY,CAAC,MAAM,EAAE,CAAC;IACxB,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC;AAxBQ,QAAA,qBAAqB,yBAwB7B"}
1
+ {"version":3,"file":"monitorCharacteristic.js","sourceRoot":"","sources":["../src/monitorCharacteristic.ts"],"names":[],"mappings":";;;AAAA,+BAAkC;AAClC,6CAAkD;AAElD,yCAA2D;AAE3D,MAAM,QAAQ,GAAG,aAAa,CAAC;AAExB,MAAM,qBAAqB,GAAG,CACnC,cAA8B,EAC9B,OAAsB,EACF,EAAE,CACtB,IAAI,iBAAU,CAAC,CAAC,CAAC,EAAE;IACjB,MAAM,MAAM,GAAG,IAAI,kBAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAClD,MAAM,CAAC,KAAK,CAAC,sCAAsC,EAAE;QACnD,kBAAkB,EAAE,cAAc,CAAC,IAAI;KACxC,CAAC,CAAC;IAEH,MAAM,YAAY,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;QACvD,IAAI,KAAK,EAAE;YACT,MAAM,CAAC,KAAK,CAAC,wCAAwC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;YAClE,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;SAChB;aAAM,IAAI,CAAC,CAAC,EAAE;YACb,MAAM,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;YACxD,CAAC,CAAC,KAAK,CACL,IAAI,uBAAc,CAAC,mCAAmC,EAAE,2BAA2B,CAAC,CACrF,CAAC;SACH;aAAM;YACL,IAAI;gBACF,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;gBAC7C,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;aACf;YAAC,OAAO,KAAK,EAAE;gBACd,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;aAChB;SACF;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,EAAE;QACV,YAAY,CAAC,MAAM,EAAE,CAAC;IACxB,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC;AAhCQ,QAAA,qBAAqB,yBAgC7B"}
@@ -3,10 +3,16 @@ import Transport from "@ledgerhq/hw-transport";
3
3
  import type { Subscription as TransportSubscription, Observer as TransportObserver } from "@ledgerhq/hw-transport";
4
4
  import { DeviceId, Device, Characteristic } from "react-native-ble-plx";
5
5
  import type { DeviceModel } from "@ledgerhq/devices";
6
+ import { TraceContext } from "@ledgerhq/logs";
6
7
  import { Observable, Observer } from "rxjs";
7
8
  import { HwTransportError } from "@ledgerhq/errors";
8
9
  import { ReconnectionConfig } from "./types";
9
10
  export declare const setReconnectionConfig: (config: ReconnectionConfig | null | undefined) => void;
11
+ /**
12
+ * react-native bluetooth BLE implementation
13
+ * @example
14
+ * import BleTransport from "@ledgerhq/react-native-hw-transport-ble";
15
+ */
10
16
  export default class BleTransport extends Transport {
11
17
  static disconnectTimeoutMs: number;
12
18
  /**
@@ -38,17 +44,21 @@ export default class BleTransport extends Transport {
38
44
  * @param observer Device is partial in order to avoid the live-common/this dep
39
45
  * @returns TransportSubscription
40
46
  */
41
- static listen(observer: TransportObserver<any, HwTransportError>): TransportSubscription;
47
+ static listen(observer: TransportObserver<any, HwTransportError>, context?: TraceContext): TransportSubscription;
42
48
  /**
43
- * Open a BLE transport
49
+ * Opens a BLE transport
50
+ *
44
51
  * @param {Device | string} deviceOrId
52
+ * @param timeoutMs TODO: to keep, used in a separate PR
53
+ * @param context An optional context object for log/tracing strategy
45
54
  */
46
- static open(deviceOrId: Device | string): Promise<BleTransport>;
55
+ static open(deviceOrId: Device | string, timeoutMs?: number, context?: TraceContext): Promise<BleTransport>;
47
56
  /**
48
- * Exposed method from the ble-plx library
57
+ * Exposes method from the ble-plx library to disconnect a device
58
+ *
49
59
  * Disconnects from {@link Device} if it's connected or cancels pending connection.
50
60
  */
51
- static disconnect: (id: DeviceId) => Promise<void>;
61
+ static disconnect: (id: DeviceId, context?: TraceContext) => Promise<void>;
52
62
  device: Device;
53
63
  deviceModel: DeviceModel;
54
64
  disconnectTimeout: null | ReturnType<typeof setTimeout>;
@@ -59,10 +69,13 @@ export default class BleTransport extends Transport {
59
69
  notYetDisconnected: boolean;
60
70
  writeCharacteristic: Characteristic;
61
71
  writeCmdCharacteristic: Characteristic | undefined;
62
- constructor(device: Device, writeCharacteristic: Characteristic, writeCmdCharacteristic: Characteristic | undefined, notifyObservable: Observable<any>, deviceModel: DeviceModel);
72
+ constructor(device: Device, writeCharacteristic: Characteristic, writeCmdCharacteristic: Characteristic | undefined, notifyObservable: Observable<any>, deviceModel: DeviceModel, { context }?: {
73
+ context?: TraceContext;
74
+ });
63
75
  /**
64
76
  * Send data to the device using a low level API.
65
77
  * It's recommended to use the "send" method for a higher level API.
78
+ *
66
79
  * @param {Buffer} apdu - The data to send.
67
80
  * @returns {Promise<Buffer>} A promise that resolves with the response data from the device.
68
81
  */
@@ -1 +1 @@
1
- {"version":3,"file":"BleTransport.d.ts","sourceRoot":"","sources":["../src/BleTransport.ts"],"names":[],"mappings":";AAAA,OAAO,SAAS,MAAM,wBAAwB,CAAC;AAC/C,OAAO,KAAK,EACV,YAAY,IAAI,qBAAqB,EACrC,QAAQ,IAAI,iBAAiB,EAC9B,MAAM,wBAAwB,CAAC;AAYhC,OAAO,EAKL,QAAQ,EACR,MAAM,EACN,cAAc,EAGf,MAAM,sBAAsB,CAAC;AAO9B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,EAAE,UAAU,EAAsC,QAAQ,EAAE,MAAM,MAAM,CAAC;AAEhF,OAAO,EAML,gBAAgB,EACjB,MAAM,kBAAkB,CAAC;AAI1B,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAW7C,eAAO,MAAM,qBAAqB,WAAY,kBAAkB,GAAG,IAAI,GAAG,SAAS,KAAG,IAErF,CAAC;AAqSF,MAAM,CAAC,OAAO,OAAO,YAAa,SAAQ,SAAS;IACjD,MAAM,CAAC,mBAAmB,SAAQ;IAClC;;OAEG;IACH,MAAM,CAAC,WAAW,QAAO,QAAQ,OAAO,CAAC,CAAsD;IAE/F;;OAEG;IACH,MAAM,CAAC,IAAI,QAAO,QAAQ,IAAI,EAAE,CAAC,CAE/B;IAEF;;;;OAIG;IACH,MAAM,CAAC,WAAW,aAAc,MAAM,KAAG,IAAI,CAM3C;IAEF;;;;;OAKG;IACH,MAAM,CAAC,YAAY,CACjB,QAAQ,EAAE,QAAQ,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,OAAO,CAAC;KACpB,CAAC,GACD,qBAAqB;IAexB;;;;OAIG;IACH,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,iBAAiB,CAAC,GAAG,EAAE,gBAAgB,CAAC,GAAG,qBAAqB;IAuDxF;;;OAGG;WACU,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAIrE;;;OAGG;IACH,MAAM,CAAC,UAAU,OAAc,QAAQ,KAAG,QAAQ,IAAI,CAAC,CAIrD;IAEF,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,WAAW,CAAC;IACzB,iBAAiB,EAAE,IAAI,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAQ;IAC/D,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,UAAQ;IACnB,OAAO,SAAM;IACb,gBAAgB,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC;IAClC,kBAAkB,UAAQ;IAC1B,mBAAmB,EAAE,cAAc,CAAC;IACpC,sBAAsB,EAAE,cAAc,GAAG,SAAS,CAAC;gBAGjD,MAAM,EAAE,MAAM,EACd,mBAAmB,EAAE,cAAc,EACnC,sBAAsB,EAAE,cAAc,GAAG,SAAS,EAClD,gBAAgB,EAAE,UAAU,CAAC,GAAG,CAAC,EACjC,WAAW,EAAE,WAAW;IAc1B;;;;;OAKG;IACH,QAAQ,SAAU,MAAM,KAAG,QAAQ,GAAG,CAAC,CA2BlC;IAEL;;;OAGG;IACG,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC;IAkCjC;;;;;OAKG;IACG,yBAAyB,CAC7B,kBAAkB,EAAE,UAAU,GAAG,MAAM,GAAG,UAAU,GACnD,OAAO,CAAC,MAAM,CAAC;IAMlB;;;;;OAKG;IACH,KAAK,WAAkB,MAAM,SAAS,MAAM,GAAG,SAAS,KAAG,QAAQ,IAAI,CAAC,CAetE;IAEF;;;;;;;OAOG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CA2B7B"}
1
+ {"version":3,"file":"BleTransport.d.ts","sourceRoot":"","sources":["../src/BleTransport.ts"],"names":[],"mappings":"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"}
@@ -21,13 +21,14 @@ import { sendAPDU } from "@ledgerhq/devices/lib/ble/sendAPDU";
21
21
  import { receiveAPDU } from "@ledgerhq/devices/lib/ble/receiveAPDU";
22
22
  import { BleManager, ConnectionPriority, BleErrorCode, LogLevel, } from "react-native-ble-plx";
23
23
  import { DeviceModelId, getBluetoothServiceUuids, getInfosForServiceUuid, } from "@ledgerhq/devices";
24
- import { log } from "@ledgerhq/logs";
25
- import { defer, merge, from, of, throwError } from "rxjs";
24
+ import { trace, LocalTracer } from "@ledgerhq/logs";
25
+ import { defer, merge, from, of, throwError, firstValueFrom } from "rxjs";
26
26
  import { share, ignoreElements, first, map, tap, catchError } from "rxjs/operators";
27
27
  import { CantOpenDevice, TransportError, DisconnectedDeviceDuringOperation, PairingFailed, PeerRemovedPairing, } from "@ledgerhq/errors";
28
28
  import { monitorCharacteristic } from "./monitorCharacteristic";
29
29
  import { awaitsBleOn } from "./awaitsBleOn";
30
30
  import { decoratePromiseErrors, remapError, mapBleErrorToHwTransportError } from "./remapErrors";
31
+ const LOG_TYPE = "ble-verbose";
31
32
  /**
32
33
  * This is potentially not needed anymore, to be checked if the bug is still
33
34
  * happening.
@@ -82,28 +83,40 @@ const bleManagerInstance = () => {
82
83
  }
83
84
  return _bleManager;
84
85
  };
85
- const clearDisconnectTimeout = (deviceId) => {
86
+ const clearDisconnectTimeout = (deviceId, context) => {
86
87
  const cachedTransport = transportsCache[deviceId];
87
88
  if (cachedTransport && cachedTransport.disconnectTimeout) {
88
- log(TAG, "Clearing queued disconnect");
89
+ trace({ type: LOG_TYPE, message: "Clearing queued disconnect", context });
89
90
  clearTimeout(cachedTransport.disconnectTimeout);
90
91
  }
91
92
  };
92
- function open(deviceOrId, needsReconnect) {
93
+ /**
94
+ * Opens a BLE connection with a given device. Returns a Transport instance.
95
+ *
96
+ * @param deviceOrId
97
+ * @param needsReconnect
98
+ * @param timeoutMs TODO: to keep, used in a separate PR
99
+ * @param context Optional tracing/log context
100
+ * @returns A BleTransport instance
101
+ */
102
+ function open(deviceOrId, needsReconnect, timeoutMs, context) {
93
103
  return __awaiter(this, void 0, void 0, function* () {
104
+ const tracer = new LocalTracer(LOG_TYPE, context);
94
105
  let device;
95
- log(TAG, `open with ${deviceOrId}`);
106
+ tracer.trace(`Opening ${deviceOrId}`, { needsReconnect });
96
107
  if (typeof deviceOrId === "string") {
97
108
  if (transportsCache[deviceOrId]) {
98
- log(TAG, "Transport in cache, using that.");
109
+ tracer.trace(`Transport in cache, using it`);
99
110
  clearDisconnectTimeout(deviceOrId);
111
+ // The cached transport probably has an older trace/log context
112
+ transportsCache[deviceOrId].setTraceContext(context);
100
113
  return transportsCache[deviceOrId];
101
114
  }
102
- log(TAG, `Tries to open device: ${deviceOrId}`);
115
+ tracer.trace(`Trying to open device: ${deviceOrId}`);
103
116
  yield awaitsBleOn(bleManagerInstance());
104
117
  // Returns a list of known devices by their identifiers
105
118
  const devices = yield bleManagerInstance().devices([deviceOrId]);
106
- log(TAG, `found ${devices.length} devices`);
119
+ tracer.trace(`Found ${devices.length} already known device(s) with given id`, { deviceOrId });
107
120
  [device] = devices;
108
121
  if (!device) {
109
122
  // Returns a list of the peripherals currently connected to the system
@@ -111,18 +124,21 @@ function open(deviceOrId, needsReconnect) {
111
124
  // connected to our app, we check that below.
112
125
  const connectedDevices = yield bleManagerInstance().connectedDevices(getBluetoothServiceUuids());
113
126
  const connectedDevicesFiltered = connectedDevices.filter(d => d.id === deviceOrId);
114
- log(TAG, `found ${connectedDevicesFiltered.length} connected devices`);
127
+ tracer.trace(`No known device with given id. Found ${connectedDevicesFiltered.length} devices from already connected devices`, { deviceOrId });
115
128
  [device] = connectedDevicesFiltered;
116
129
  }
117
130
  if (!device) {
118
131
  // We still don't have a device, so we attempt to connect to it.
119
- log(TAG, `connectToDevice(${deviceOrId})`);
132
+ tracer.trace(`No known nor connected devices with given id. Trying to connect to device`, {
133
+ deviceOrId,
134
+ timeoutMs,
135
+ });
120
136
  // Nb ConnectionOptions dropped since it's not used internally by ble-plx.
121
137
  try {
122
138
  device = yield bleManagerInstance().connectToDevice(deviceOrId, connectOptions);
123
139
  }
124
140
  catch (e) {
125
- log(TAG, `error code ${e.errorCode}`);
141
+ tracer.trace(`Error code: ${e.errorCode}`);
126
142
  if (e.errorCode === BleErrorCode.DeviceMTUChangeFailed) {
127
143
  // If the MTU update did not work, we try to connect without requesting for a specific MTU
128
144
  connectOptions = {};
@@ -142,21 +158,22 @@ function open(deviceOrId, needsReconnect) {
142
158
  device = deviceOrId;
143
159
  }
144
160
  if (!(yield device.isConnected())) {
145
- log(TAG, "not connected. connecting...");
161
+ tracer.trace(`Device found but not connected. connecting...`, { timeoutMs, connectOptions });
146
162
  try {
147
- yield device.connect(connectOptions);
163
+ yield device.connect(Object.assign({}, connectOptions));
148
164
  }
149
- catch (e) {
150
- log("ble-verbose", `connect error - ${JSON.stringify(e)}`);
151
- if (e.errorCode === BleErrorCode.DeviceMTUChangeFailed) {
152
- log("ble-verbose", `device.mtu=${device.mtu}, reconnecting`);
165
+ catch (error) {
166
+ tracer.trace(`Connect error`, { error });
167
+ if (error.errorCode === BleErrorCode.DeviceMTUChangeFailed) {
168
+ tracer.trace(`Device mtu=${device.mtu}, reconnecting`);
153
169
  connectOptions = {};
154
170
  yield device.connect();
155
171
  }
156
- else if (e.iosErrorCode === 14 || e.reason === "Peer removed pairing information") {
157
- log("ble-verbose", "iOS broken pairing");
158
- log("ble-verbose", JSON.stringify(device));
159
- log("ble-verbose", JSON.stringify(bluetoothInfoCache[device.id]));
172
+ else if (error.iosErrorCode === 14 || error.reason === "Peer removed pairing information") {
173
+ tracer.trace(`iOS broken pairing`, {
174
+ device,
175
+ bluetoothInfoCache: bluetoothInfoCache[device.id],
176
+ });
160
177
  const { deviceModel } = bluetoothInfoCache[device.id] || {};
161
178
  const { productName } = deviceModel || {};
162
179
  throw new PeerRemovedPairing(undefined, {
@@ -165,10 +182,11 @@ function open(deviceOrId, needsReconnect) {
165
182
  });
166
183
  }
167
184
  else {
168
- throw remapError(e);
185
+ throw remapError(error);
169
186
  }
170
187
  }
171
188
  }
189
+ tracer.trace(`Device is connected now, getting services and characteristics`);
172
190
  yield device.discoverAllServicesAndCharacteristics();
173
191
  let res = retrieveInfos(device);
174
192
  let characteristics;
@@ -185,6 +203,7 @@ function open(deviceOrId, needsReconnect) {
185
203
  }
186
204
  }
187
205
  if (!res) {
206
+ tracer.trace(`Service not found`);
188
207
  throw new TransportError("service not found", "BLEServiceNotFound");
189
208
  }
190
209
  const { deviceModel, serviceUuid, writeUuid, writeCmdUuid, notifyUuid } = res;
@@ -192,6 +211,7 @@ function open(deviceOrId, needsReconnect) {
192
211
  characteristics = yield device.characteristicsForService(serviceUuid);
193
212
  }
194
213
  if (!characteristics) {
214
+ tracer.trace(`Characteristics not found`);
195
215
  throw new TransportError("service not found", "BLEServiceNotFound");
196
216
  }
197
217
  let writeC;
@@ -225,31 +245,36 @@ function open(deviceOrId, needsReconnect) {
225
245
  throw new TransportError("write cmd characteristic not writableWithoutResponse", "BLECharacteristicInvalid");
226
246
  }
227
247
  }
228
- log(TAG, `device.mtu=${device.mtu}`);
229
- const notifyObservable = monitorCharacteristic(notifyC).pipe(catchError(e => {
248
+ tracer.trace(`device.mtu=${device.mtu}`);
249
+ const notifyObservable = monitorCharacteristic(notifyC, context).pipe(catchError(e => {
230
250
  // LL-9033 fw 2.0.2 introduced this case, we silence the inner unhandled error.
231
251
  const msg = String(e);
232
- return msg.includes("notify change failed") ? of(new PairingFailed(msg)) : throwError(e);
252
+ return msg.includes("notify change failed")
253
+ ? of(new PairingFailed(msg))
254
+ : throwError(() => e);
233
255
  }), tap(value => {
234
256
  if (value instanceof PairingFailed)
235
257
  return;
236
- log("ble-frame", "<= " + value.toString("hex"));
258
+ trace({ type: "ble-frame", message: `<= ${value.toString("hex")}`, context });
237
259
  }), share());
238
260
  const notif = notifyObservable.subscribe();
239
- const transport = new BleTransport(device, writeC, writeCmdC, notifyObservable, deviceModel);
261
+ const transport = new BleTransport(device, writeC, writeCmdC, notifyObservable, deviceModel, {
262
+ context,
263
+ });
264
+ tracer.trace(`New BleTransport created`);
240
265
  // Keeping it as a comment for now but if no new bluetooth issues occur, we will be able to remove it
241
266
  // await transport.requestConnectionPriority("High");
242
267
  // eslint-disable-next-line prefer-const
243
268
  let disconnectedSub;
244
- const onDisconnect = (e) => {
269
+ const onDisconnect = (error) => {
245
270
  transport.isConnected = false;
246
271
  transport.notYetDisconnected = false;
247
272
  notif.unsubscribe();
248
273
  disconnectedSub === null || disconnectedSub === void 0 ? void 0 : disconnectedSub.remove();
249
274
  clearDisconnectTimeout(transport.id);
250
275
  delete transportsCache[transport.id];
251
- log(TAG, `BleTransport(${transport.id}) disconnected`);
252
- transport.emit("disconnect", e);
276
+ tracer.trace(`On device disconnected callback: cleared cached transport for ${transport.id}, emitting Transport event "disconnect"`, { reason: error });
277
+ transport.emit("disconnect", error);
253
278
  };
254
279
  // eslint-disable-next-line require-atomic-updates
255
280
  transportsCache[transport.id] = transport;
@@ -273,7 +298,7 @@ function open(deviceOrId, needsReconnect) {
273
298
  needsReconnect = false;
274
299
  }
275
300
  else if (deviceModel.id === DeviceModelId.stax) {
276
- log(TAG, "skipping needsReconnect for stax");
301
+ tracer.trace(`Skipping "needsReconnect" strategy for Stax`);
277
302
  needsReconnect = false;
278
303
  }
279
304
  if (needsReconnect) {
@@ -286,8 +311,8 @@ function open(deviceOrId, needsReconnect) {
286
311
  }
287
312
  }
288
313
  if (needsReconnect) {
289
- log(TAG, "reconnecting");
290
- return open(device, false);
314
+ tracer.trace(`Reconnecting`);
315
+ return open(device, false, timeoutMs, context);
291
316
  }
292
317
  return transport;
293
318
  });
@@ -297,7 +322,6 @@ function open(deviceOrId, needsReconnect) {
297
322
  * @example
298
323
  * import BleTransport from "@ledgerhq/react-native-hw-transport-ble";
299
324
  */
300
- const TAG = "ble-verbose";
301
325
  class BleTransport extends Transport {
302
326
  /**
303
327
  * Listen to state changes on the bleManagerInstance and notify the
@@ -322,8 +346,9 @@ class BleTransport extends Transport {
322
346
  * @param observer Device is partial in order to avoid the live-common/this dep
323
347
  * @returns TransportSubscription
324
348
  */
325
- static listen(observer) {
326
- log(TAG, "listening for devices");
349
+ static listen(observer, context) {
350
+ const tracer = new LocalTracer(LOG_TYPE, context);
351
+ tracer.trace("Listening for devices ...");
327
352
  let unsubscribed;
328
353
  const stateSub = bleManagerInstance().onStateChange((state) => __awaiter(this, void 0, void 0, function* () {
329
354
  if (state === "PoweredOn") {
@@ -332,7 +357,7 @@ class BleTransport extends Transport {
332
357
  if (unsubscribed)
333
358
  return;
334
359
  if (devices.length) {
335
- log(TAG, "disconnecting from devices");
360
+ tracer.trace("Disconnecting from all devices", { deviceCount: devices.length });
336
361
  yield Promise.all(devices.map(d => BleTransport.disconnect(d.id).catch(() => { })));
337
362
  }
338
363
  if (unsubscribed)
@@ -359,23 +384,26 @@ class BleTransport extends Transport {
359
384
  unsubscribed = true;
360
385
  bleManagerInstance().stopDeviceScan();
361
386
  stateSub.remove();
362
- log(TAG, "done listening.");
387
+ tracer.trace("Done listening");
363
388
  };
364
389
  return {
365
390
  unsubscribe,
366
391
  };
367
392
  }
368
393
  /**
369
- * Open a BLE transport
394
+ * Opens a BLE transport
395
+ *
370
396
  * @param {Device | string} deviceOrId
397
+ * @param timeoutMs TODO: to keep, used in a separate PR
398
+ * @param context An optional context object for log/tracing strategy
371
399
  */
372
- static open(deviceOrId) {
400
+ static open(deviceOrId, timeoutMs, context) {
373
401
  return __awaiter(this, void 0, void 0, function* () {
374
- return open(deviceOrId, true);
402
+ return open(deviceOrId, true, timeoutMs, context);
375
403
  });
376
404
  }
377
- constructor(device, writeCharacteristic, writeCmdCharacteristic, notifyObservable, deviceModel) {
378
- super();
405
+ constructor(device, writeCharacteristic, writeCmdCharacteristic, notifyObservable, deviceModel, { context } = {}) {
406
+ super({ context, logType: LOG_TYPE });
379
407
  this.disconnectTimeout = null;
380
408
  this.isConnected = true;
381
409
  this.mtuSize = 20;
@@ -383,29 +411,40 @@ class BleTransport extends Transport {
383
411
  /**
384
412
  * Send data to the device using a low level API.
385
413
  * It's recommended to use the "send" method for a higher level API.
414
+ *
386
415
  * @param {Buffer} apdu - The data to send.
387
416
  * @returns {Promise<Buffer>} A promise that resolves with the response data from the device.
388
417
  */
389
- this.exchange = (apdu) => this.exchangeAtomicImpl(() => __awaiter(this, void 0, void 0, function* () {
390
- try {
391
- const msgIn = apdu.toString("hex");
392
- log("apdu", `=> ${msgIn}`);
393
- const data = yield merge(this.notifyObservable.pipe(receiveAPDU), sendAPDU(this.write, apdu, this.mtuSize)).toPromise();
394
- const msgOut = data.toString("hex");
395
- log("apdu", `<= ${msgOut}`);
396
- return data;
397
- }
398
- catch (e) {
399
- log("ble-error", "exchange got " + String(e));
400
- if (this.notYetDisconnected) {
401
- // in such case we will always disconnect because something is bad.
402
- yield bleManagerInstance()
403
- .cancelDeviceConnection(this.id)
404
- .catch(() => { }); // but we ignore if disconnect worked.
418
+ this.exchange = (apdu) => {
419
+ const tracer = this.tracer.withUpdatedContext({
420
+ function: "exchange",
421
+ });
422
+ tracer.trace("Exchanging APDU ...");
423
+ return this.exchangeAtomicImpl(() => __awaiter(this, void 0, void 0, function* () {
424
+ try {
425
+ const msgIn = apdu.toString("hex");
426
+ tracer.withType("apdu").trace(`=> ${msgIn}`);
427
+ const data = yield firstValueFrom(merge(this.notifyObservable.pipe(receiveAPDU), sendAPDU(this.write, apdu, this.mtuSize)));
428
+ const msgOut = data.toString("hex");
429
+ tracer.withType("apdu").trace(`<= ${msgOut}`);
430
+ return data;
405
431
  }
406
- throw remapError(e);
407
- }
408
- }));
432
+ catch (error) {
433
+ tracer.withType("ble-error").trace(`Error while exchanging APDU`, { error });
434
+ if (this.notYetDisconnected) {
435
+ // in such case we will always disconnect because something is bad.
436
+ yield bleManagerInstance()
437
+ .cancelDeviceConnection(this.id)
438
+ .catch(() => { }); // but we ignore if disconnect worked.
439
+ }
440
+ const mappedError = remapError(error);
441
+ tracer.trace("Error while exchanging APDU, mapped and throws following error", {
442
+ mappedError,
443
+ });
444
+ throw mappedError;
445
+ }
446
+ }));
447
+ };
409
448
  /**
410
449
  * Do not call this directly unless you know what you're doing. Communication
411
450
  * with a Ledger device should be through the {@link exchange} method.
@@ -413,22 +452,18 @@ class BleTransport extends Transport {
413
452
  * @param txid
414
453
  */
415
454
  this.write = (buffer, txid) => __awaiter(this, void 0, void 0, function* () {
416
- log("ble-frame", "=> " + buffer.toString("hex"));
417
- if (!this.writeCmdCharacteristic) {
418
- try {
455
+ try {
456
+ if (!this.writeCmdCharacteristic) {
419
457
  yield this.writeCharacteristic.writeWithResponse(buffer.toString("base64"), txid);
420
458
  }
421
- catch (e) {
422
- throw new DisconnectedDeviceDuringOperation(e.message);
423
- }
424
- }
425
- else {
426
- try {
459
+ else {
427
460
  yield this.writeCmdCharacteristic.writeWithoutResponse(buffer.toString("base64"), txid);
428
461
  }
429
- catch (e) {
430
- throw new DisconnectedDeviceDuringOperation(e.message);
431
- }
462
+ this.tracer.withType("ble-frame").trace("=> " + buffer.toString("hex"));
463
+ }
464
+ catch (error) {
465
+ this.tracer.trace("Error while writing APDU", { error });
466
+ throw new DisconnectedDeviceDuringOperation(error instanceof Error ? error.message : `${error}`);
432
467
  }
433
468
  });
434
469
  this.id = device.id;
@@ -437,8 +472,8 @@ class BleTransport extends Transport {
437
472
  this.writeCmdCharacteristic = writeCmdCharacteristic;
438
473
  this.notifyObservable = notifyObservable;
439
474
  this.deviceModel = deviceModel;
440
- log(TAG, `BleTransport(${String(this.id)}) new instance`);
441
475
  clearDisconnectTimeout(this.id);
476
+ this.tracer.trace(`New instance of BleTransport for device ${this.id}`);
442
477
  }
443
478
  /**
444
479
  * Negotiate with the device the maximum transfer unit for the ble frames
@@ -447,24 +482,32 @@ class BleTransport extends Transport {
447
482
  inferMTU() {
448
483
  return __awaiter(this, void 0, void 0, function* () {
449
484
  let { mtu } = this.device;
485
+ this.tracer.trace(`Inferring MTU ...`, { currentDeviceMtu: mtu });
450
486
  yield this.exchangeAtomicImpl(() => __awaiter(this, void 0, void 0, function* () {
451
487
  try {
452
- mtu = yield merge(this.notifyObservable.pipe(tap(maybeError => {
488
+ mtu = yield firstValueFrom(merge(this.notifyObservable.pipe(tap(maybeError => {
453
489
  if (maybeError instanceof Error)
454
490
  throw maybeError;
455
- }), first(buffer => buffer.readUInt8(0) === 0x08), map(buffer => buffer.readUInt8(5))), defer(() => from(this.write(Buffer.from([0x08, 0, 0, 0, 0])))).pipe(ignoreElements())).toPromise();
491
+ }), first(buffer => buffer.readUInt8(0) === 0x08), map(buffer => buffer.readUInt8(5))), defer(() => from(this.write(Buffer.from([0x08, 0, 0, 0, 0])))).pipe(ignoreElements())));
456
492
  }
457
- catch (e) {
458
- log("ble-error", "inferMTU got " + JSON.stringify(e));
493
+ catch (error) {
494
+ this.tracer.withType("ble-error").trace("Error while inferring MTU", { mtu });
459
495
  yield bleManagerInstance()
460
496
  .cancelDeviceConnection(this.id)
461
497
  .catch(() => { }); // but we ignore if disconnect worked.
462
- throw remapError(e);
498
+ const mappedError = remapError(error);
499
+ this.tracer.trace("Error while inferring APDU, mapped and throws following error", {
500
+ mappedError,
501
+ });
502
+ throw mappedError;
463
503
  }
464
504
  }));
505
+ this.tracer.trace(`Successfully negotiated MTU with device`, {
506
+ mtu,
507
+ mtuSize: this.mtuSize,
508
+ });
465
509
  if (mtu > 20) {
466
510
  this.mtuSize = mtu;
467
- log(TAG, `BleTransport(${this.id}) mtu set to ${this.mtuSize}`);
468
511
  }
469
512
  return this.mtuSize;
470
513
  });
@@ -490,16 +533,15 @@ class BleTransport extends Transport {
490
533
  */
491
534
  close() {
492
535
  return __awaiter(this, void 0, void 0, function* () {
536
+ this.tracer.trace("Closing, queuing a disconnect ...");
493
537
  let resolve;
494
538
  const disconnectPromise = new Promise(innerResolve => {
495
539
  resolve = innerResolve;
496
540
  });
497
541
  clearDisconnectTimeout(this.id);
498
- log(TAG, "Queuing a disconnect");
499
542
  this.disconnectTimeout = setTimeout(() => {
500
- log(TAG, `Triggering a disconnect from ${this.id}`);
501
543
  if (this.isConnected) {
502
- BleTransport.disconnect(this.id)
544
+ BleTransport.disconnect(this.id, this.tracer.getContext())
503
545
  .catch(() => { })
504
546
  .finally(resolve);
505
547
  }
@@ -540,13 +582,22 @@ BleTransport.setLogLevel = (logLevel) => {
540
582
  }
541
583
  };
542
584
  /**
543
- * Exposed method from the ble-plx library
585
+ * Exposes method from the ble-plx library to disconnect a device
586
+ *
544
587
  * Disconnects from {@link Device} if it's connected or cancels pending connection.
545
588
  */
546
- BleTransport.disconnect = (id) => __awaiter(void 0, void 0, void 0, function* () {
547
- log(TAG, `user disconnect(${id})`);
589
+ BleTransport.disconnect = (id, context) => __awaiter(void 0, void 0, void 0, function* () {
590
+ trace({
591
+ type: LOG_TYPE,
592
+ message: `Trying to disconnect device ${id})`,
593
+ context,
594
+ });
548
595
  yield bleManagerInstance().cancelDeviceConnection(id);
549
- log(TAG, "disconnected");
596
+ trace({
597
+ type: LOG_TYPE,
598
+ message: `Device ${id} disconnected`,
599
+ context,
600
+ });
550
601
  });
551
602
  export default BleTransport;
552
603
  //# sourceMappingURL=BleTransport.js.map