@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.
- package/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +11 -0
- package/lib/BleTransport.d.ts.map +1 -1
- package/lib/BleTransport.js +424 -623
- package/lib/BleTransport.js.map +1 -1
- package/lib/BleTransport.test.js +146 -248
- package/lib/BleTransport.test.js.map +1 -1
- package/lib/awaitsBleOn.js +25 -28
- package/lib/awaitsBleOn.js.map +1 -1
- package/lib/monitorCharacteristic.js +26 -28
- package/lib/monitorCharacteristic.js.map +1 -1
- package/lib/remapErrors.d.ts +3 -1
- package/lib/remapErrors.d.ts.map +1 -1
- package/lib/remapErrors.js +22 -13
- package/lib/remapErrors.js.map +1 -1
- package/lib/timer.js +12 -12
- package/lib/timer.js.map +1 -1
- package/lib/types.d.ts +3 -3
- package/lib/types.d.ts.map +1 -1
- package/lib/types.js +1 -1
- package/lib-es/BleTransport.d.ts.map +1 -1
- package/lib-es/BleTransport.js +412 -612
- package/lib-es/BleTransport.js.map +1 -1
- package/lib-es/BleTransport.test.js +143 -245
- package/lib-es/BleTransport.test.js.map +1 -1
- package/lib-es/awaitsBleOn.js +21 -24
- package/lib-es/awaitsBleOn.js.map +1 -1
- package/lib-es/monitorCharacteristic.js +22 -24
- package/lib-es/monitorCharacteristic.js.map +1 -1
- package/lib-es/remapErrors.d.ts +3 -1
- package/lib-es/remapErrors.d.ts.map +1 -1
- package/lib-es/remapErrors.js +22 -13
- package/lib-es/remapErrors.js.map +1 -1
- package/lib-es/timer.js +10 -10
- package/lib-es/timer.js.map +1 -1
- package/lib-es/types.d.ts +3 -3
- package/lib-es/types.d.ts.map +1 -1
- package/package.json +6 -7
- package/src/BleTransport.test.ts +22 -2
- package/src/BleTransport.ts +27 -8
- package/src/remapErrors.ts +17 -3
package/lib-es/awaitsBleOn.js
CHANGED
|
@@ -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
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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,
|
|
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
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
|
-
|
|
16
|
-
|
|
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,
|
|
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"}
|
package/lib-es/remapErrors.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { HwTransportError, HwTransportErrorType } from "@ledgerhq/errors";
|
|
2
2
|
import { BleError, BleErrorCode } from "react-native-ble-plx";
|
|
3
|
-
|
|
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,
|
|
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"}
|
package/lib-es/remapErrors.js
CHANGED
|
@@ -1,21 +1,30 @@
|
|
|
1
|
-
import { DisconnectedDevice, HwTransportError, HwTransportErrorType, } from "@ledgerhq/errors";
|
|
2
|
-
import { BleErrorCode } from "react-native-ble-plx";
|
|
3
|
-
export
|
|
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
|
|
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
|
|
23
|
+
export const rethrowError = (e) => {
|
|
13
24
|
throw remapError(e);
|
|
14
25
|
};
|
|
15
|
-
export
|
|
16
|
-
|
|
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
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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,
|
|
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
|
-
|
|
1
|
+
const timer = process.env.NODE_ENV === "development"
|
|
2
2
|
? {
|
|
3
|
-
timeout:
|
|
3
|
+
timeout: (fn, ms) => {
|
|
4
4
|
// hack for a bug in RN https://github.com/facebook/react-native/issues/9030
|
|
5
|
-
|
|
6
|
-
|
|
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
|
|
12
|
+
return () => {
|
|
13
13
|
clearInterval(interval);
|
|
14
14
|
};
|
|
15
|
-
}
|
|
15
|
+
},
|
|
16
16
|
}
|
|
17
17
|
: {
|
|
18
|
-
timeout:
|
|
19
|
-
|
|
20
|
-
return
|
|
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
|
package/lib-es/timer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timer.js","sourceRoot":"","sources":["../src/timer.ts"],"names":[],"mappings":"AAAA,
|
|
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
|
|
3
|
-
export
|
|
4
|
-
export
|
|
2
|
+
export type Device = any;
|
|
3
|
+
export type Characteristic = any;
|
|
4
|
+
export type ReconnectionConfig = {
|
|
5
5
|
pairingThreshold: number;
|
|
6
6
|
delayAfterFirstPairing: number;
|
|
7
7
|
};
|
package/lib-es/types.d.ts.map
CHANGED
|
@@ -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,
|
|
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.
|
|
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.
|
|
33
|
-
"@ledgerhq/errors": "^6.12.
|
|
34
|
-
"@ledgerhq/hw-transport": "^6.28.
|
|
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
|
|
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",
|
package/src/BleTransport.test.ts
CHANGED
|
@@ -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
|
|
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(
|
|
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) => {
|
package/src/BleTransport.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
|
643
|
+
ConnectionPriority[connectionPriority]
|
|
625
644
|
)
|
|
626
645
|
);
|
|
627
646
|
}
|
package/src/remapErrors.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
) {
|