@ledgerhq/react-native-hw-transport-ble 6.28.5 → 6.28.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.
Files changed (41) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +11 -0
  3. package/lib/BleTransport.d.ts.map +1 -1
  4. package/lib/BleTransport.js +424 -623
  5. package/lib/BleTransport.js.map +1 -1
  6. package/lib/BleTransport.test.js +146 -248
  7. package/lib/BleTransport.test.js.map +1 -1
  8. package/lib/awaitsBleOn.js +25 -28
  9. package/lib/awaitsBleOn.js.map +1 -1
  10. package/lib/monitorCharacteristic.js +26 -28
  11. package/lib/monitorCharacteristic.js.map +1 -1
  12. package/lib/remapErrors.d.ts +3 -1
  13. package/lib/remapErrors.d.ts.map +1 -1
  14. package/lib/remapErrors.js +22 -13
  15. package/lib/remapErrors.js.map +1 -1
  16. package/lib/timer.js +12 -12
  17. package/lib/timer.js.map +1 -1
  18. package/lib/types.d.ts +3 -3
  19. package/lib/types.d.ts.map +1 -1
  20. package/lib/types.js +1 -1
  21. package/lib-es/BleTransport.d.ts.map +1 -1
  22. package/lib-es/BleTransport.js +412 -612
  23. package/lib-es/BleTransport.js.map +1 -1
  24. package/lib-es/BleTransport.test.js +143 -245
  25. package/lib-es/BleTransport.test.js.map +1 -1
  26. package/lib-es/awaitsBleOn.js +21 -24
  27. package/lib-es/awaitsBleOn.js.map +1 -1
  28. package/lib-es/monitorCharacteristic.js +22 -24
  29. package/lib-es/monitorCharacteristic.js.map +1 -1
  30. package/lib-es/remapErrors.d.ts +3 -1
  31. package/lib-es/remapErrors.d.ts.map +1 -1
  32. package/lib-es/remapErrors.js +22 -13
  33. package/lib-es/remapErrors.js.map +1 -1
  34. package/lib-es/timer.js +10 -10
  35. package/lib-es/timer.js.map +1 -1
  36. package/lib-es/types.d.ts +3 -3
  37. package/lib-es/types.d.ts.map +1 -1
  38. package/package.json +6 -7
  39. package/src/BleTransport.test.ts +22 -2
  40. package/src/BleTransport.ts +27 -8
  41. package/src/remapErrors.ts +17 -3
@@ -1,31 +1,28 @@
1
1
  import { BluetoothRequired } from "@ledgerhq/errors";
2
2
  import { log } from "@ledgerhq/logs";
3
3
  import timer from "./timer";
4
- export var awaitsBleOn = function (bleManager, ms) {
5
- if (ms === void 0) { ms = 3000; }
6
- return new Promise(function (resolve, reject) {
7
- var done = false;
8
- var lastState = "Unknown";
9
- var stateSub = bleManager.onStateChange(function (state) {
10
- lastState = state;
11
- log("ble-verbose", "ble state -> ".concat(state));
12
- if (state === "PoweredOn") {
13
- if (done)
14
- return;
15
- removeTimeout();
16
- done = true;
17
- stateSub.remove();
18
- resolve();
19
- }
20
- }, true);
21
- var removeTimeout = timer.timeout(function () {
4
+ export const awaitsBleOn = (bleManager, ms = 3000) => new Promise((resolve, reject) => {
5
+ let done = false;
6
+ let lastState = "Unknown";
7
+ const stateSub = bleManager.onStateChange((state) => {
8
+ lastState = state;
9
+ log("ble-verbose", `ble state -> ${state}`);
10
+ if (state === "PoweredOn") {
22
11
  if (done)
23
12
  return;
13
+ removeTimeout();
14
+ done = true;
24
15
  stateSub.remove();
25
- reject(new BluetoothRequired("", {
26
- state: lastState
27
- }));
28
- }, ms);
29
- });
30
- };
16
+ resolve();
17
+ }
18
+ }, true);
19
+ const removeTimeout = timer.timeout(() => {
20
+ if (done)
21
+ return;
22
+ stateSub.remove();
23
+ reject(new BluetoothRequired("", {
24
+ state: lastState,
25
+ }));
26
+ }, ms);
27
+ });
31
28
  //# sourceMappingURL=awaitsBleOn.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"awaitsBleOn.js","sourceRoot":"","sources":["../src/awaitsBleOn.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AACrC,OAAO,KAAK,MAAM,SAAS,CAAC;AAE5B,MAAM,CAAC,IAAM,WAAW,GAAG,UAAC,UAAsB,EAAE,EAAS;IAAT,mBAAA,EAAA,SAAS;IAC3D,OAAA,IAAI,OAAO,CAAC,UAAC,OAAO,EAAE,MAAM;QAC1B,IAAI,IAAI,GAAG,KAAK,CAAC;QACjB,IAAI,SAAS,GAAG,SAAS,CAAC;QAC1B,IAAM,QAAQ,GAAG,UAAU,CAAC,aAAa,CAAC,UAAC,KAAK;YAC9C,SAAS,GAAG,KAAK,CAAC;YAClB,GAAG,CAAC,aAAa,EAAE,uBAAgB,KAAK,CAAE,CAAC,CAAC;YAE5C,IAAI,KAAK,KAAK,WAAW,EAAE;gBACzB,IAAI,IAAI;oBAAE,OAAO;gBACjB,aAAa,EAAE,CAAC;gBAChB,IAAI,GAAG,IAAI,CAAC;gBACZ,QAAQ,CAAC,MAAM,EAAE,CAAC;gBAClB,OAAO,EAAE,CAAC;aACX;QACH,CAAC,EAAE,IAAI,CAAC,CAAC;QACT,IAAM,aAAa,GAAG,KAAK,CAAC,OAAO,CAAC;YAClC,IAAI,IAAI;gBAAE,OAAO;YACjB,QAAQ,CAAC,MAAM,EAAE,CAAC;YAClB,MAAM,CACJ,IAAI,iBAAiB,CAAC,EAAE,EAAE;gBACxB,KAAK,EAAE,SAAS;aACjB,CAAC,CACH,CAAC;QACJ,CAAC,EAAE,EAAE,CAAC,CAAC;IACT,CAAC,CAAC;AAxBF,CAwBE,CAAC"}
1
+ {"version":3,"file":"awaitsBleOn.js","sourceRoot":"","sources":["../src/awaitsBleOn.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AACrC,OAAO,KAAK,MAAM,SAAS,CAAC;AAE5B,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,UAAsB,EAAE,EAAE,GAAG,IAAI,EAAiB,EAAE,CAC9E,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;IAC9B,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,IAAI,SAAS,GAAG,SAAS,CAAC;IAC1B,MAAM,QAAQ,GAAG,UAAU,CAAC,aAAa,CAAC,CAAC,KAAK,EAAE,EAAE;QAClD,SAAS,GAAG,KAAK,CAAC;QAClB,GAAG,CAAC,aAAa,EAAE,gBAAgB,KAAK,EAAE,CAAC,CAAC;QAE5C,IAAI,KAAK,KAAK,WAAW,EAAE;YACzB,IAAI,IAAI;gBAAE,OAAO;YACjB,aAAa,EAAE,CAAC;YAChB,IAAI,GAAG,IAAI,CAAC;YACZ,QAAQ,CAAC,MAAM,EAAE,CAAC;YAClB,OAAO,EAAE,CAAC;SACX;IACH,CAAC,EAAE,IAAI,CAAC,CAAC;IACT,MAAM,aAAa,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;QACvC,IAAI,IAAI;YAAE,OAAO;QACjB,QAAQ,CAAC,MAAM,EAAE,CAAC;QAClB,MAAM,CACJ,IAAI,iBAAiB,CAAC,EAAE,EAAE;YACxB,KAAK,EAAE,SAAS;SACjB,CAAC,CACH,CAAC;IACJ,CAAC,EAAE,EAAE,CAAC,CAAC;AACT,CAAC,CAAC,CAAC"}
@@ -1,31 +1,29 @@
1
1
  import { Observable } from "rxjs";
2
2
  import { TransportError } from "@ledgerhq/errors";
3
3
  import { log } from "@ledgerhq/logs";
4
- export var monitorCharacteristic = function (characteristic) {
5
- return new Observable(function (o) {
6
- log("ble-verbose", "start monitor " + characteristic.uuid);
7
- var subscription = characteristic.monitor(function (error, c) {
8
- if (error) {
9
- log("ble-verbose", "error monitor " + characteristic.uuid + ": " + error);
10
- o.error(error);
11
- }
12
- else if (!c) {
13
- o.error(new TransportError("characteristic monitor null value", "CharacteristicMonitorNull"));
4
+ export const monitorCharacteristic = (characteristic) => new Observable((o) => {
5
+ log("ble-verbose", "start monitor " + characteristic.uuid);
6
+ const subscription = characteristic.monitor((error, c) => {
7
+ if (error) {
8
+ log("ble-verbose", "error monitor " + characteristic.uuid + ": " + error);
9
+ o.error(error);
10
+ }
11
+ else if (!c) {
12
+ o.error(new TransportError("characteristic monitor null value", "CharacteristicMonitorNull"));
13
+ }
14
+ else {
15
+ try {
16
+ const value = Buffer.from(c.value, "base64");
17
+ o.next(value);
14
18
  }
15
- else {
16
- try {
17
- var value = Buffer.from(c.value, "base64");
18
- o.next(value);
19
- }
20
- catch (error) {
21
- o.error(error);
22
- }
19
+ catch (error) {
20
+ o.error(error);
23
21
  }
24
- });
25
- return function () {
26
- log("ble-verbose", "end monitor " + characteristic.uuid);
27
- subscription.remove();
28
- };
22
+ }
29
23
  });
30
- };
24
+ return () => {
25
+ log("ble-verbose", "end monitor " + characteristic.uuid);
26
+ subscription.remove();
27
+ };
28
+ });
31
29
  //# sourceMappingURL=monitorCharacteristic.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"monitorCharacteristic.js","sourceRoot":"","sources":["../src/monitorCharacteristic.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAClC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AACrC,MAAM,CAAC,IAAM,qBAAqB,GAAG,UACnC,cAA8B;IAE9B,OAAA,IAAI,UAAU,CAAC,UAAC,CAAC;QACf,GAAG,CAAC,aAAa,EAAE,gBAAgB,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;QAC3D,IAAM,YAAY,GAAG,cAAc,CAAC,OAAO,CAAC,UAAC,KAAK,EAAE,CAAC;YACnD,IAAI,KAAK,EAAE;gBACT,GAAG,CACD,aAAa,EACb,gBAAgB,GAAG,cAAc,CAAC,IAAI,GAAG,IAAI,GAAG,KAAK,CACtD,CAAC;gBACF,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;aAChB;iBAAM,IAAI,CAAC,CAAC,EAAE;gBACb,CAAC,CAAC,KAAK,CACL,IAAI,cAAc,CAChB,mCAAmC,EACnC,2BAA2B,CAC5B,CACF,CAAC;aACH;iBAAM;gBACL,IAAI;oBACF,IAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;oBAC7C,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;iBACf;gBAAC,OAAO,KAAK,EAAE;oBACd,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;iBAChB;aACF;QACH,CAAC,CAAC,CAAC;QACH,OAAO;YACL,GAAG,CAAC,aAAa,EAAE,cAAc,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;YACzD,YAAY,CAAC,MAAM,EAAE,CAAC;QACxB,CAAC,CAAC;IACJ,CAAC,CAAC;AA7BF,CA6BE,CAAC"}
1
+ {"version":3,"file":"monitorCharacteristic.js","sourceRoot":"","sources":["../src/monitorCharacteristic.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAClC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AACrC,MAAM,CAAC,MAAM,qBAAqB,GAAG,CACnC,cAA8B,EACV,EAAE,CACtB,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE;IACnB,GAAG,CAAC,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,GAAG,CACD,aAAa,EACb,gBAAgB,GAAG,cAAc,CAAC,IAAI,GAAG,IAAI,GAAG,KAAK,CACtD,CAAC;YACF,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;SAChB;aAAM,IAAI,CAAC,CAAC,EAAE;YACb,CAAC,CAAC,KAAK,CACL,IAAI,cAAc,CAChB,mCAAmC,EACnC,2BAA2B,CAC5B,CACF,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,GAAG,CAAC,aAAa,EAAE,cAAc,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;QACzD,YAAY,CAAC,MAAM,EAAE,CAAC;IACxB,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC"}
@@ -1,8 +1,10 @@
1
1
  import { HwTransportError, HwTransportErrorType } from "@ledgerhq/errors";
2
2
  import { BleError, BleErrorCode } from "react-native-ble-plx";
3
- export declare const remapError: (error: Error | null | undefined) => Error | null | undefined;
3
+ type IOBleErrorRemap = Error | BleError | null | undefined;
4
+ export declare const remapError: (error: IOBleErrorRemap) => IOBleErrorRemap;
4
5
  export declare const rethrowError: (e: Error | null | undefined) => never;
5
6
  export declare const decoratePromiseErrors: <A>(promise: Promise<A>) => Promise<A>;
6
7
  export declare const bleErrorToHwTransportError: Map<BleErrorCode, HwTransportErrorType>;
7
8
  export declare const mapBleErrorToHwTransportError: (bleError: BleError) => HwTransportError;
9
+ export {};
8
10
  //# sourceMappingURL=remapErrors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"remapErrors.d.ts","sourceRoot":"","sources":["../src/remapErrors.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,gBAAgB,EAChB,oBAAoB,EACrB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAE9D,eAAO,MAAM,UAAU,UAAW,KAAK,GAAG,IAAI,GAAG,SAAS,6BAWzD,CAAC;AAEF,eAAO,MAAM,YAAY,MAAO,KAAK,GAAG,IAAI,GAAG,SAAS,KAAG,KAE1D,CAAC;AAEF,eAAO,MAAM,qBAAqB,wCACL,CAAC;AAE9B,eAAO,MAAM,0BAA0B,yCAWrC,CAAC;AAEH,eAAO,MAAM,6BAA6B,aAC9B,QAAQ,KACjB,gBAOF,CAAC"}
1
+ {"version":3,"file":"remapErrors.d.ts","sourceRoot":"","sources":["../src/remapErrors.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,gBAAgB,EAChB,oBAAoB,EAGrB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAmB,QAAQ,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAE/E,KAAK,eAAe,GAAG,KAAK,GAAG,QAAQ,GAAG,IAAI,GAAG,SAAS,CAAC;AAC3D,eAAO,MAAM,UAAU,UAAW,eAAe,KAAG,eAsBnD,CAAC;AAEF,eAAO,MAAM,YAAY,MAAO,KAAK,GAAG,IAAI,GAAG,SAAS,KAAG,KAE1D,CAAC;AAEF,eAAO,MAAM,qBAAqB,wCACL,CAAC;AAE9B,eAAO,MAAM,0BAA0B,yCAWrC,CAAC;AAEH,eAAO,MAAM,6BAA6B,aAC9B,QAAQ,KACjB,gBAOF,CAAC"}
@@ -1,21 +1,30 @@
1
- import { DisconnectedDevice, HwTransportError, HwTransportErrorType, } from "@ledgerhq/errors";
2
- import { BleErrorCode } from "react-native-ble-plx";
3
- export var remapError = function (error) {
1
+ import { DisconnectedDevice, HwTransportError, HwTransportErrorType, PairingFailed, PeerRemovedPairing, } from "@ledgerhq/errors";
2
+ import { BleATTErrorCode, BleError, BleErrorCode } from "react-native-ble-plx";
3
+ export const remapError = (error) => {
4
4
  if (!error || !error.message)
5
5
  return error;
6
- if (error.message.includes("was disconnected") ||
6
+ if (error instanceof BleError) {
7
+ if (error.iosErrorCode === BleATTErrorCode.UnlikelyError ||
8
+ error.reason === "Peer removed pairing information") {
9
+ return new PeerRemovedPairing();
10
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
11
+ // @ts-ignore It's not documented but seems to match a refusal on Android pairing
12
+ }
13
+ else if ((error === null || error === void 0 ? void 0 : error.attErrorCode) === 22) {
14
+ return new PairingFailed();
15
+ }
16
+ }
17
+ else if (error.message.includes("was disconnected") ||
7
18
  error.message.includes("not found")) {
8
19
  return new DisconnectedDevice();
9
20
  }
10
21
  return error;
11
22
  };
12
- export var rethrowError = function (e) {
23
+ export const rethrowError = (e) => {
13
24
  throw remapError(e);
14
25
  };
15
- export var decoratePromiseErrors = function (promise) {
16
- return promise["catch"](rethrowError);
17
- };
18
- export var bleErrorToHwTransportError = new Map([
26
+ export const decoratePromiseErrors = (promise) => promise.catch(rethrowError);
27
+ export const bleErrorToHwTransportError = new Map([
19
28
  [BleErrorCode.ScanStartFailed, HwTransportErrorType.BluetoothScanStartFailed],
20
29
  [
21
30
  BleErrorCode.LocationServicesDisabled,
@@ -27,10 +36,10 @@ export var bleErrorToHwTransportError = new Map([
27
36
  HwTransportErrorType.LocationServicesUnauthorized,
28
37
  ],
29
38
  ]);
30
- export var mapBleErrorToHwTransportError = function (bleError) {
31
- var message = "".concat(bleError.message, ". Origin: ").concat(bleError.errorCode);
32
- var inferedType = bleErrorToHwTransportError.get(bleError.errorCode);
33
- var type = !inferedType ? HwTransportErrorType.Unknown : inferedType;
39
+ export const mapBleErrorToHwTransportError = (bleError) => {
40
+ const message = `${bleError.message}. Origin: ${bleError.errorCode}`;
41
+ const inferedType = bleErrorToHwTransportError.get(bleError.errorCode);
42
+ const type = !inferedType ? HwTransportErrorType.Unknown : inferedType;
34
43
  return new HwTransportError(type, message);
35
44
  };
36
45
  //# sourceMappingURL=remapErrors.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"remapErrors.js","sourceRoot":"","sources":["../src/remapErrors.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAY,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAE9D,MAAM,CAAC,IAAM,UAAU,GAAG,UAAC,KAA+B;IACxD,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IAE3C,IACE,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC;QAC1C,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,EACnC;QACA,OAAO,IAAI,kBAAkB,EAAE,CAAC;KACjC;IAED,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,MAAM,CAAC,IAAM,YAAY,GAAG,UAAC,CAA2B;IACtD,MAAM,UAAU,CAAC,CAAC,CAAC,CAAC;AACtB,CAAC,CAAC;AAEF,MAAM,CAAC,IAAM,qBAAqB,GAAG,UAAI,OAAmB;IAC1D,OAAA,OAAO,CAAC,OAAK,CAAA,CAAC,YAAY,CAAC;AAA3B,CAA2B,CAAC;AAE9B,MAAM,CAAC,IAAM,0BAA0B,GAAG,IAAI,GAAG,CAAC;IAChD,CAAC,YAAY,CAAC,eAAe,EAAE,oBAAoB,CAAC,wBAAwB,CAAC;IAC7E;QACE,YAAY,CAAC,wBAAwB;QACrC,oBAAoB,CAAC,wBAAwB;KAC9C;IACD;QACE,kFAAkF;QAClF,YAAY,CAAC,qBAAqB;QAClC,oBAAoB,CAAC,4BAA4B;KAClD;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,IAAM,6BAA6B,GAAG,UAC3C,QAAkB;IAElB,IAAM,OAAO,GAAG,UAAG,QAAQ,CAAC,OAAO,uBAAa,QAAQ,CAAC,SAAS,CAAE,CAAC;IAErE,IAAM,WAAW,GAAG,0BAA0B,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;IACvE,IAAM,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC;IAEvE,OAAO,IAAI,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAC7C,CAAC,CAAC"}
1
+ {"version":3,"file":"remapErrors.js","sourceRoot":"","sources":["../src/remapErrors.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,aAAa,EACb,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAG/E,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAAsB,EAAmB,EAAE;IACpE,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IAE3C,IAAI,KAAK,YAAY,QAAQ,EAAE;QAC7B,IACE,KAAK,CAAC,YAAY,KAAK,eAAe,CAAC,aAAa;YACpD,KAAK,CAAC,MAAM,KAAK,kCAAkC,EACnD;YACA,OAAO,IAAI,kBAAkB,EAAE,CAAC;YAChC,6DAA6D;YAC7D,iFAAiF;SAClF;aAAM,IAAI,CAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,YAAY,MAAK,EAAE,EAAE;YACrC,OAAO,IAAI,aAAa,EAAE,CAAC;SAC5B;KACF;SAAM,IACL,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC;QAC1C,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,EACnC;QACA,OAAO,IAAI,kBAAkB,EAAE,CAAC;KACjC;IAED,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAA2B,EAAS,EAAE;IACjE,MAAM,UAAU,CAAC,CAAC,CAAC,CAAC;AACtB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAI,OAAmB,EAAc,EAAE,CAC1E,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;AAE9B,MAAM,CAAC,MAAM,0BAA0B,GAAG,IAAI,GAAG,CAAC;IAChD,CAAC,YAAY,CAAC,eAAe,EAAE,oBAAoB,CAAC,wBAAwB,CAAC;IAC7E;QACE,YAAY,CAAC,wBAAwB;QACrC,oBAAoB,CAAC,wBAAwB;KAC9C;IACD;QACE,kFAAkF;QAClF,YAAY,CAAC,qBAAqB;QAClC,oBAAoB,CAAC,4BAA4B;KAClD;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAC3C,QAAkB,EACA,EAAE;IACpB,MAAM,OAAO,GAAG,GAAG,QAAQ,CAAC,OAAO,aAAa,QAAQ,CAAC,SAAS,EAAE,CAAC;IAErE,MAAM,WAAW,GAAG,0BAA0B,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;IACvE,MAAM,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC;IAEvE,OAAO,IAAI,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAC7C,CAAC,CAAC"}
package/lib-es/timer.js CHANGED
@@ -1,24 +1,24 @@
1
- var timer = process.env.NODE_ENV === "development"
1
+ const timer = process.env.NODE_ENV === "development"
2
2
  ? {
3
- timeout: function (fn, ms) {
3
+ timeout: (fn, ms) => {
4
4
  // hack for a bug in RN https://github.com/facebook/react-native/issues/9030
5
- var startTime = Date.now();
6
- var interval = setInterval(function () {
5
+ const startTime = Date.now();
6
+ const interval = setInterval(() => {
7
7
  if (Date.now() - startTime >= ms) {
8
8
  clearInterval(interval);
9
9
  fn();
10
10
  }
11
11
  }, 100);
12
- return function () {
12
+ return () => {
13
13
  clearInterval(interval);
14
14
  };
15
- }
15
+ },
16
16
  }
17
17
  : {
18
- timeout: function (fn, ms) {
19
- var timeout = setTimeout(fn, ms);
20
- return function () { return clearTimeout(timeout); };
21
- }
18
+ timeout: (fn, ms) => {
19
+ const timeout = setTimeout(fn, ms);
20
+ return () => clearTimeout(timeout);
21
+ },
22
22
  };
23
23
  export default timer;
24
24
  //# sourceMappingURL=timer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"timer.js","sourceRoot":"","sources":["../src/timer.ts"],"names":[],"mappings":"AAAA,IAAM,KAAK,GACT,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa;IACpC,CAAC,CAAC;QACE,OAAO,EAAE,UAAC,EAAgC,EAAE,EAAU;YACpD,4EAA4E;YAC5E,IAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAC7B,IAAM,QAAQ,GAAG,WAAW,CAAC;gBAC3B,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,IAAI,EAAE,EAAE;oBAChC,aAAa,CAAC,QAAQ,CAAC,CAAC;oBACxB,EAAE,EAAE,CAAC;iBACN;YACH,CAAC,EAAE,GAAG,CAAC,CAAC;YACR,OAAO;gBACL,aAAa,CAAC,QAAQ,CAAC,CAAC;YAC1B,CAAC,CAAC;QACJ,CAAC;KACF;IACH,CAAC,CAAC;QACE,OAAO,EAAE,UAAC,EAAgC,EAAE,EAAU;YACpD,IAAM,OAAO,GAAG,UAAU,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACnC,OAAO,cAAM,OAAA,YAAY,CAAC,OAAO,CAAC,EAArB,CAAqB,CAAC;QACrC,CAAC;KACF,CAAC;AACR,eAAe,KAAK,CAAC"}
1
+ {"version":3,"file":"timer.js","sourceRoot":"","sources":["../src/timer.ts"],"names":[],"mappings":"AAAA,MAAM,KAAK,GACT,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa;IACpC,CAAC,CAAC;QACE,OAAO,EAAE,CAAC,EAAgC,EAAE,EAAU,EAAE,EAAE;YACxD,4EAA4E;YAC5E,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAC7B,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE;gBAChC,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,IAAI,EAAE,EAAE;oBAChC,aAAa,CAAC,QAAQ,CAAC,CAAC;oBACxB,EAAE,EAAE,CAAC;iBACN;YACH,CAAC,EAAE,GAAG,CAAC,CAAC;YACR,OAAO,GAAG,EAAE;gBACV,aAAa,CAAC,QAAQ,CAAC,CAAC;YAC1B,CAAC,CAAC;QACJ,CAAC;KACF;IACH,CAAC,CAAC;QACE,OAAO,EAAE,CAAC,EAAgC,EAAE,EAAU,EAAE,EAAE;YACxD,MAAM,OAAO,GAAG,UAAU,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACnC,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QACrC,CAAC;KACF,CAAC;AACR,eAAe,KAAK,CAAC"}
package/lib-es/types.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export type { BleManager } from "react-native-ble-plx";
2
- export declare type Device = any;
3
- export declare type Characteristic = any;
4
- export declare type ReconnectionConfig = {
2
+ export type Device = any;
3
+ export type Characteristic = any;
4
+ export type ReconnectionConfig = {
5
5
  pairingThreshold: number;
6
6
  delayAfterFirstPairing: number;
7
7
  };
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,oBAAY,MAAM,GAAG,GAAG,CAAC;AACzB,oBAAY,cAAc,GAAG,GAAG,CAAC;AAEjC,oBAAY,kBAAkB,GAAG;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,sBAAsB,EAAE,MAAM,CAAC;CAChC,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,MAAM,MAAM,MAAM,GAAG,GAAG,CAAC;AACzB,MAAM,MAAM,cAAc,GAAG,GAAG,CAAC;AAEjC,MAAM,MAAM,kBAAkB,GAAG;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,sBAAsB,EAAE,MAAM,CAAC;CAChC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ledgerhq/react-native-hw-transport-ble",
3
- "version": "6.28.5",
3
+ "version": "6.28.6-nightly.0",
4
4
  "description": "Ledger Hardware Wallet Bluetooth BLE transport for React Native",
5
5
  "keywords": [
6
6
  "Ledger",
@@ -29,9 +29,9 @@
29
29
  "react-native-ble-plx": "2.0.3",
30
30
  "rxjs": "6",
31
31
  "uuid": "^3.4.0",
32
- "@ledgerhq/devices": "^8.0.1",
33
- "@ledgerhq/errors": "^6.12.4",
34
- "@ledgerhq/hw-transport": "^6.28.2",
32
+ "@ledgerhq/devices": "^8.0.2-nightly.0",
33
+ "@ledgerhq/errors": "^6.12.5-nightly.0",
34
+ "@ledgerhq/hw-transport": "^6.28.3-nightly.0",
35
35
  "@ledgerhq/logs": "^6.10.1"
36
36
  },
37
37
  "gitHead": "dd0dea64b58e5a9125c8a422dcffd29e5ef6abec",
@@ -40,11 +40,10 @@
40
40
  "@types/node": "^18.15.3",
41
41
  "documentation": "13.2.4",
42
42
  "jest": "^28.1.1",
43
- "rimraf": "^4.1.2",
43
+ "rimraf": "^4.4.1",
44
44
  "source-map-support": "^0.5.21",
45
45
  "ts-jest": "^28.0.5",
46
- "ts-node": "^10.4.0",
47
- "typescript": "^4"
46
+ "ts-node": "^10.4.0"
48
47
  },
49
48
  "scripts": {
50
49
  "clean": "rimraf lib lib-es",
@@ -12,7 +12,17 @@ import { Subscription } from "rxjs";
12
12
  * to cover test cases. It should be noted that this mock is not comprehensive
13
13
  * and may require further refinement to meet all requirements.
14
14
  */
15
+
15
16
  jest.mock("react-native-ble-plx", () => {
17
+ class BleError {
18
+ iosErrorCode: number;
19
+ reason: string;
20
+ constructor(iosErrorCode: number, reason: string) {
21
+ this.iosErrorCode = iosErrorCode;
22
+ this.reason = reason;
23
+ }
24
+ }
25
+
16
26
  // Set of callbacks that we can trigger from our tests.
17
27
  const callbacks: { [key: string]: (...args: any[]) => void } = {};
18
28
 
@@ -20,6 +30,12 @@ jest.mock("react-native-ble-plx", () => {
20
30
  BleErrorCode: {
21
31
  ScanStartFailed: 0,
22
32
  },
33
+ BleError,
34
+ ConnectionPriority: {
35
+ Balanced: 0,
36
+ High: 1,
37
+ LowPower: 2,
38
+ },
23
39
  BleManager: function () {
24
40
  const dynamicProps = {
25
41
  isConnected: true,
@@ -53,6 +69,10 @@ jest.mock("react-native-ble-plx", () => {
53
69
  manufacturerData: null,
54
70
  solicitedServiceUUIDs: null,
55
71
 
72
+ requestConnectionPriority: async () => {
73
+ return null; // Should return self.
74
+ },
75
+
56
76
  isConnected: () => {
57
77
  return dynamicProps.isConnected;
58
78
  },
@@ -116,7 +136,7 @@ jest.mock("react-native-ble-plx", () => {
116
136
  serviceID: 105553179758272,
117
137
  writeWithoutResponse: async (raw) => {
118
138
  if (!dynamicProps.isConnected)
119
- throw new Error("Device is not connected");
139
+ throw new BleError(22, "Device is not connected");
120
140
 
121
141
  const hex = Buffer.from(raw, "base64").toString("hex");
122
142
  let value: Buffer;
@@ -246,7 +266,7 @@ describe("BleTransport connectivity test coverage", () => {
246
266
  await BleTransport.disconnect(deviceId);
247
267
  await expect(
248
268
  transport.exchange(Buffer.from("b010000000", "hex"))
249
- ).rejects.toThrow("Device is not connected"); // More specific errors some day.
269
+ ).rejects.toThrow(); // More specific errors some day.
250
270
  });
251
271
 
252
272
  it("should disconnect if close is called, even if pending response", (done) => {
@@ -1,4 +1,8 @@
1
1
  import Transport from "@ledgerhq/hw-transport";
2
+ import type {
3
+ Subscription as TransportSubscription,
4
+ Observer as TransportObserver,
5
+ } from "@ledgerhq/hw-transport";
2
6
  // ---------------------------------------------------------------------------------------------
3
7
  // Since this is a react-native library and metro bundler does not support
4
8
  // package exports yet (see: https://github.com/facebook/metro/issues/670)
@@ -10,10 +14,6 @@ import Transport from "@ledgerhq/hw-transport";
10
14
  import { sendAPDU } from "@ledgerhq/devices/lib/ble/sendAPDU";
11
15
  import { receiveAPDU } from "@ledgerhq/devices/lib/ble/receiveAPDU";
12
16
 
13
- import type {
14
- Subscription as TransportSubscription,
15
- Observer as TransportObserver,
16
- } from "@ledgerhq/hw-transport";
17
17
  import {
18
18
  BleManager,
19
19
  ConnectionPriority,
@@ -46,14 +46,15 @@ import {
46
46
  TransportError,
47
47
  DisconnectedDeviceDuringOperation,
48
48
  PairingFailed,
49
+ PeerRemovedPairing,
49
50
  HwTransportError,
50
51
  } from "@ledgerhq/errors";
51
52
  import { monitorCharacteristic } from "./monitorCharacteristic";
52
53
  import { awaitsBleOn } from "./awaitsBleOn";
53
54
  import {
54
55
  decoratePromiseErrors,
55
- mapBleErrorToHwTransportError,
56
56
  remapError,
57
+ mapBleErrorToHwTransportError,
57
58
  } from "./remapErrors";
58
59
  import { ReconnectionConfig } from "./types";
59
60
 
@@ -78,6 +79,9 @@ const retrieveInfos = (device: Device | null) => {
78
79
  if (!serviceUUID) return;
79
80
  const infos = getInfosForServiceUuid(serviceUUID);
80
81
  if (!infos) return;
82
+
83
+ // If we retrieved information, update the cache
84
+ bluetoothInfoCache[device.id] = infos;
81
85
  return infos;
82
86
  };
83
87
 
@@ -90,6 +94,7 @@ const delay = (ms: number | undefined) =>
90
94
  * @type {Object.<string, BluetoothTransport>}
91
95
  */
92
96
  const transportsCache: { [deviceId: string]: BleTransport } = {};
97
+ const bluetoothInfoCache: { [deviceUuid: string]: BluetoothInfos } = {}; // Allows us to give more granulary error messages.
93
98
 
94
99
  // connectOptions is actually used by react-native-ble-plx even if comment above ConnectionOptions says it's not used
95
100
  let connectOptions: Record<string, unknown> = {
@@ -191,12 +196,26 @@ async function open(deviceOrId: Device | string, needsReconnect: boolean) {
191
196
  try {
192
197
  await device.connect(connectOptions);
193
198
  } catch (e: any) {
199
+ log("ble-verbose", `connect error - ${JSON.stringify(e)}`);
194
200
  if (e.errorCode === BleErrorCode.DeviceMTUChangeFailed) {
195
- // If the MTU update did not work, we try to connect without requesting for a specific MTU
201
+ log("ble-verbose", `device.mtu=${device.mtu}, reconnecting`);
196
202
  connectOptions = {};
197
203
  await device.connect();
204
+ } else if (
205
+ e.iosErrorCode === 14 ||
206
+ e.reason === "Peer removed pairing information"
207
+ ) {
208
+ log("ble-verbose", "iOS broken pairing");
209
+ log("ble-verbose", JSON.stringify(device));
210
+ log("ble-verbose", JSON.stringify(bluetoothInfoCache[device.id]));
211
+ const { deviceModel } = bluetoothInfoCache[device.id] || {};
212
+ const { productName } = deviceModel || {};
213
+ throw new PeerRemovedPairing(undefined, {
214
+ deviceName: device.name,
215
+ productName,
216
+ });
198
217
  } else {
199
- throw e;
218
+ throw remapError(e);
200
219
  }
201
220
  }
202
221
  }
@@ -621,7 +640,7 @@ export default class BleTransport extends Transport {
621
640
  ): Promise<Device> {
622
641
  return await decoratePromiseErrors(
623
642
  this.device.requestConnectionPriority(
624
- ConnectionPriority[connectionPriority as keyof ConnectionPriority]
643
+ ConnectionPriority[connectionPriority]
625
644
  )
626
645
  );
627
646
  }
@@ -2,13 +2,27 @@ import {
2
2
  DisconnectedDevice,
3
3
  HwTransportError,
4
4
  HwTransportErrorType,
5
+ PairingFailed,
6
+ PeerRemovedPairing,
5
7
  } from "@ledgerhq/errors";
6
- import { BleError, BleErrorCode } from "react-native-ble-plx";
8
+ import { BleATTErrorCode, BleError, BleErrorCode } from "react-native-ble-plx";
7
9
 
8
- export const remapError = (error: Error | null | undefined) => {
10
+ type IOBleErrorRemap = Error | BleError | null | undefined;
11
+ export const remapError = (error: IOBleErrorRemap): IOBleErrorRemap => {
9
12
  if (!error || !error.message) return error;
10
13
 
11
- if (
14
+ if (error instanceof BleError) {
15
+ if (
16
+ error.iosErrorCode === BleATTErrorCode.UnlikelyError ||
17
+ error.reason === "Peer removed pairing information"
18
+ ) {
19
+ return new PeerRemovedPairing();
20
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
21
+ // @ts-ignore It's not documented but seems to match a refusal on Android pairing
22
+ } else if (error?.attErrorCode === 22) {
23
+ return new PairingFailed();
24
+ }
25
+ } else if (
12
26
  error.message.includes("was disconnected") ||
13
27
  error.message.includes("not found")
14
28
  ) {