@onekeyfe/hd-transport-react-native 1.2.2-alpha.117 → 1.2.2-alpha.119
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/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -3
- package/package.json +5 -5
- package/src/__tests__/protocolV2Link.test.ts +108 -0
- package/src/index.ts +29 -8
package/dist/index.d.ts
CHANGED
|
@@ -252,7 +252,8 @@ declare class ReactNativeBleTransport {
|
|
|
252
252
|
/**
|
|
253
253
|
* A sleeping Classic drops GetFeatures/Ping and only leaves its screensaver on Initialize, which
|
|
254
254
|
* resets the wallet session, so it is sent once after a fully silent detection. The firmware does
|
|
255
|
-
* not reliably answer it, so its timeout must not drop the link.
|
|
255
|
+
* not reliably answer it, so its timeout must not drop the link. It only runs when V1 is probed
|
|
256
|
+
* first, so a late reply lands on the V1 probe rather than on a V2 one.
|
|
256
257
|
*/
|
|
257
258
|
private wakeSilentProtocolV1Device;
|
|
258
259
|
private resetProbeStateAfterProtocolProbe;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1229,10 +1229,29 @@ class ReactNativeBleTransport {
|
|
|
1229
1229
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
1230
1230
|
Log === null || Log === void 0 ? void 0 : Log.debug('[ReactNativeBleTransport] post-connect MTU timed out, reconnecting without requesting MTU');
|
|
1231
1231
|
const timedOutDevice = device;
|
|
1232
|
-
|
|
1232
|
+
let mtuTeardownSettled = false;
|
|
1233
|
+
yield this.runNativeTeardown(uuid, blePlxManager, () => __awaiter(this, void 0, void 0, function* () {
|
|
1234
|
+
yield this.runBestEffortNativeOperation('mtu timeout: cancel device connection', () => timedOutDevice.cancelConnection());
|
|
1235
|
+
mtuTeardownSettled = true;
|
|
1236
|
+
}));
|
|
1233
1237
|
if (this.stopped)
|
|
1234
1238
|
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleDeviceDisconnected);
|
|
1235
|
-
|
|
1239
|
+
if (!mtuTeardownSettled || this.blePlxManager !== blePlxManager) {
|
|
1240
|
+
throw hdShared.ERRORS.TypedError(hdShared.HardwareErrorCode.BleTimeoutError, 'BLE MTU cleanup timed out');
|
|
1241
|
+
}
|
|
1242
|
+
try {
|
|
1243
|
+
device = yield this.connectWithTimeout(uuid, () => timedOutDevice.connect(fallbackConnectOptions));
|
|
1244
|
+
}
|
|
1245
|
+
catch (error) {
|
|
1246
|
+
if (shouldRethrowBleSetupError(error))
|
|
1247
|
+
throw error;
|
|
1248
|
+
if ((error === null || error === void 0 ? void 0 : error.errorCode) === reactNativeBlePlx.BleErrorCode.DeviceAlreadyConnected) {
|
|
1249
|
+
device = timedOutDevice;
|
|
1250
|
+
}
|
|
1251
|
+
else {
|
|
1252
|
+
remapError(error);
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1236
1255
|
}
|
|
1237
1256
|
}
|
|
1238
1257
|
if (this.stopped)
|
|
@@ -2292,7 +2311,7 @@ class ReactNativeBleTransport {
|
|
|
2292
2311
|
wakeSilentProtocolV1Device(uuid, probeOrder) {
|
|
2293
2312
|
return __awaiter(this, void 0, void 0, function* () {
|
|
2294
2313
|
if (reactNative.Platform.OS !== 'android' ||
|
|
2295
|
-
|
|
2314
|
+
probeOrder[0] !== 'V1' ||
|
|
2296
2315
|
this.silentDetections.get(uuid) !== 'silent') {
|
|
2297
2316
|
return;
|
|
2298
2317
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onekeyfe/hd-transport-react-native",
|
|
3
|
-
"version": "1.2.2-alpha.
|
|
3
|
+
"version": "1.2.2-alpha.119",
|
|
4
4
|
"homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -20,11 +20,11 @@
|
|
|
20
20
|
"lint:fix": "eslint . --fix"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@onekeyfe/hd-core": "1.2.2-alpha.
|
|
24
|
-
"@onekeyfe/hd-shared": "1.2.2-alpha.
|
|
25
|
-
"@onekeyfe/hd-transport": "1.2.2-alpha.
|
|
23
|
+
"@onekeyfe/hd-core": "1.2.2-alpha.119",
|
|
24
|
+
"@onekeyfe/hd-shared": "1.2.2-alpha.119",
|
|
25
|
+
"@onekeyfe/hd-transport": "1.2.2-alpha.119",
|
|
26
26
|
"@onekeyfe/react-native-ble-utils": "0.1.6",
|
|
27
27
|
"react-native-ble-plx": "3.5.1"
|
|
28
28
|
},
|
|
29
|
-
"gitHead": "
|
|
29
|
+
"gitHead": "222ec4a49467e77a73766a07227069d76d9116f6"
|
|
30
30
|
}
|
|
@@ -1151,6 +1151,99 @@ describe('ReactNativeBleTransport Protocol V2 link lifecycle', () => {
|
|
|
1151
1151
|
await transport.release(uuid, true);
|
|
1152
1152
|
}, 10_000);
|
|
1153
1153
|
|
|
1154
|
+
test('keeps the iOS link when the MTU-timeout reconnect reports it is still connected', async () => {
|
|
1155
|
+
const { BleError: BleErrorMock, BleErrorCode } = jest.requireMock('react-native-ble-plx');
|
|
1156
|
+
const { transport, uuid, device, bleManager } = createHarness();
|
|
1157
|
+
device.mtu = 23;
|
|
1158
|
+
device.requestMTU.mockImplementationOnce(() => new Promise(() => {}));
|
|
1159
|
+
device.connect.mockRejectedValueOnce(
|
|
1160
|
+
Object.assign(new BleErrorMock('Device already connected'), {
|
|
1161
|
+
errorCode: BleErrorCode.DeviceAlreadyConnected,
|
|
1162
|
+
})
|
|
1163
|
+
);
|
|
1164
|
+
|
|
1165
|
+
await expect(transport.acquire({ uuid })).resolves.toEqual({
|
|
1166
|
+
uuid,
|
|
1167
|
+
protocolType: 'V2',
|
|
1168
|
+
});
|
|
1169
|
+
expect(device.cancelConnection).toHaveBeenCalledTimes(1);
|
|
1170
|
+
expect(device.connect).toHaveBeenCalledTimes(1);
|
|
1171
|
+
expect(device.requestMTU).toHaveBeenCalledTimes(1);
|
|
1172
|
+
expect(bleManager.destroy).not.toHaveBeenCalled();
|
|
1173
|
+
expect((transport as any).getCachedTransport(uuid).mtuSize).toBe(23);
|
|
1174
|
+
await transport.release(uuid, true);
|
|
1175
|
+
}, 10_000);
|
|
1176
|
+
|
|
1177
|
+
test('reconnects after an iOS MTU timeout when cancelling the timed-out link fails', async () => {
|
|
1178
|
+
const { BleError: BleErrorMock, BleErrorCode } = jest.requireMock('react-native-ble-plx');
|
|
1179
|
+
const { transport, uuid, device, bleManager } = createHarness();
|
|
1180
|
+
device.mtu = 23;
|
|
1181
|
+
device.requestMTU.mockImplementationOnce(() => new Promise(() => {}));
|
|
1182
|
+
device.cancelConnection.mockRejectedValueOnce(
|
|
1183
|
+
Object.assign(new BleErrorMock('Operation was cancelled'), {
|
|
1184
|
+
errorCode: BleErrorCode.OperationCancelled,
|
|
1185
|
+
})
|
|
1186
|
+
);
|
|
1187
|
+
|
|
1188
|
+
await expect(transport.acquire({ uuid })).resolves.toEqual({
|
|
1189
|
+
uuid,
|
|
1190
|
+
protocolType: 'V2',
|
|
1191
|
+
});
|
|
1192
|
+
expect(device.connect).toHaveBeenCalledTimes(1);
|
|
1193
|
+
expect(device.connect.mock.calls[0]?.[0]).not.toHaveProperty('requestMTU');
|
|
1194
|
+
expect(bleManager.destroy).not.toHaveBeenCalled();
|
|
1195
|
+
await transport.release(uuid, true);
|
|
1196
|
+
}, 10_000);
|
|
1197
|
+
|
|
1198
|
+
test('maps a stale bond from the iOS MTU-timeout reconnect', async () => {
|
|
1199
|
+
const { BleError: BleErrorMock } = jest.requireMock('react-native-ble-plx');
|
|
1200
|
+
const { transport, uuid, device } = createHarness();
|
|
1201
|
+
device.mtu = 23;
|
|
1202
|
+
device.requestMTU.mockImplementationOnce(() => new Promise(() => {}));
|
|
1203
|
+
device.connect.mockRejectedValueOnce(
|
|
1204
|
+
Object.assign(new BleErrorMock('Peer removed pairing information'), {
|
|
1205
|
+
errorCode: 200,
|
|
1206
|
+
iosErrorCode: 14,
|
|
1207
|
+
})
|
|
1208
|
+
);
|
|
1209
|
+
|
|
1210
|
+
await expect(transport.acquire({ uuid })).rejects.toMatchObject({
|
|
1211
|
+
errorCode: HardwareErrorCode.BlePeerRemovedPairingInformation,
|
|
1212
|
+
});
|
|
1213
|
+
await transport.release(uuid, true).catch(() => undefined);
|
|
1214
|
+
}, 10_000);
|
|
1215
|
+
|
|
1216
|
+
test('bounds a hung iOS MTU-timeout teardown and resets the BLE manager without reconnecting', async () => {
|
|
1217
|
+
const { transport, uuid, device, bleManager } = createHarness();
|
|
1218
|
+
device.mtu = 23;
|
|
1219
|
+
device.requestMTU.mockImplementationOnce(() => new Promise(() => {}));
|
|
1220
|
+
device.cancelConnection.mockImplementationOnce(() => new Promise(() => {}));
|
|
1221
|
+
|
|
1222
|
+
await expect(transport.acquire({ uuid })).rejects.toMatchObject({
|
|
1223
|
+
errorCode: HardwareErrorCode.BleTimeoutError,
|
|
1224
|
+
message: expect.stringContaining('BLE MTU cleanup timed out'),
|
|
1225
|
+
});
|
|
1226
|
+
expect(bleManager.destroy).toHaveBeenCalledTimes(1);
|
|
1227
|
+
expect(transport.blePlxManager).toBeUndefined();
|
|
1228
|
+
expect(device.connect).not.toHaveBeenCalled();
|
|
1229
|
+
expect((transport as any).lifecycleOperations.has(uuid)).toBe(false);
|
|
1230
|
+
}, 15_000);
|
|
1231
|
+
|
|
1232
|
+
test('does not reconnect after a hung iOS MTU-timeout teardown when the manager reset is already pending', async () => {
|
|
1233
|
+
const { transport, uuid, device, bleManager } = createHarness();
|
|
1234
|
+
device.mtu = 23;
|
|
1235
|
+
device.requestMTU.mockImplementationOnce(() => new Promise(() => {}));
|
|
1236
|
+
device.cancelConnection.mockImplementationOnce(() => new Promise(() => {}));
|
|
1237
|
+
// Another device's reset is still draining, so this teardown timeout cannot swap the manager.
|
|
1238
|
+
jest.spyOn(transport as any, 'resetPlxManager').mockImplementation(() => undefined);
|
|
1239
|
+
|
|
1240
|
+
await expect(transport.acquire({ uuid })).rejects.toMatchObject({
|
|
1241
|
+
errorCode: HardwareErrorCode.BleTimeoutError,
|
|
1242
|
+
});
|
|
1243
|
+
expect(transport.blePlxManager).toBe(bleManager);
|
|
1244
|
+
expect(device.connect).not.toHaveBeenCalled();
|
|
1245
|
+
}, 15_000);
|
|
1246
|
+
|
|
1154
1247
|
test('does not request MTU again after connect falls back without requestMTU', async () => {
|
|
1155
1248
|
const { BleError: BleErrorMock, BleErrorCode } = jest.requireMock('react-native-ble-plx');
|
|
1156
1249
|
const { transport, uuid, device } = createHarness();
|
|
@@ -1560,6 +1653,21 @@ describe('ReactNativeBleTransport Protocol V2 link lifecycle', () => {
|
|
|
1560
1653
|
expect(callProtocolV1).not.toHaveBeenCalled();
|
|
1561
1654
|
});
|
|
1562
1655
|
|
|
1656
|
+
test('does not send the Initialize wake before a V2-first probe', async () => {
|
|
1657
|
+
setPlatformOS('android');
|
|
1658
|
+
const { transport, uuid } = createHarness();
|
|
1659
|
+
const probes = transport as any;
|
|
1660
|
+
jest.spyOn(probes, 'probeProtocolV1').mockResolvedValue(false);
|
|
1661
|
+
jest.spyOn(probes, 'probeProtocolV2').mockResolvedValue(false);
|
|
1662
|
+
const callProtocolV1 = jest.spyOn(probes, 'callProtocolV1').mockResolvedValue({});
|
|
1663
|
+
|
|
1664
|
+
await expect(transport.acquire({ uuid, protocolHint: 'V2' })).rejects.toBeDefined();
|
|
1665
|
+
// Silent now, but the next detection probes V2 first: a late V1 reply would land on
|
|
1666
|
+
// the V2 probe, so no Initialize is sent.
|
|
1667
|
+
await expect(transport.acquire({ uuid, protocolHint: 'V2' })).rejects.toBeDefined();
|
|
1668
|
+
expect(callProtocolV1).not.toHaveBeenCalled();
|
|
1669
|
+
});
|
|
1670
|
+
|
|
1563
1671
|
test('does not send the Initialize wake on iOS', async () => {
|
|
1564
1672
|
const { transport, uuid } = createHarness();
|
|
1565
1673
|
const probes = transport as any;
|
package/src/index.ts
CHANGED
|
@@ -1320,13 +1320,33 @@ export default class ReactNativeBleTransport {
|
|
|
1320
1320
|
'[ReactNativeBleTransport] post-connect MTU timed out, reconnecting without requesting MTU'
|
|
1321
1321
|
);
|
|
1322
1322
|
const timedOutDevice = device;
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1323
|
+
let mtuTeardownSettled = false;
|
|
1324
|
+
await this.runNativeTeardown(uuid, blePlxManager, async () => {
|
|
1325
|
+
await this.runBestEffortNativeOperation('mtu timeout: cancel device connection', () =>
|
|
1326
|
+
timedOutDevice.cancelConnection()
|
|
1327
|
+
);
|
|
1328
|
+
mtuTeardownSettled = true;
|
|
1329
|
+
});
|
|
1326
1330
|
if (this.stopped) throw ERRORS.TypedError(HardwareErrorCode.BleDeviceDisconnected);
|
|
1327
|
-
|
|
1328
|
-
timedOutDevice.
|
|
1329
|
-
|
|
1331
|
+
if (!mtuTeardownSettled || this.blePlxManager !== blePlxManager) {
|
|
1332
|
+
// The teardown budget expired and the manager that owned timedOutDevice was reset.
|
|
1333
|
+
throw ERRORS.TypedError(HardwareErrorCode.BleTimeoutError, 'BLE MTU cleanup timed out');
|
|
1334
|
+
}
|
|
1335
|
+
try {
|
|
1336
|
+
device = await this.connectWithTimeout(uuid, () =>
|
|
1337
|
+
timedOutDevice.connect(fallbackConnectOptions)
|
|
1338
|
+
);
|
|
1339
|
+
} catch (error) {
|
|
1340
|
+
if (shouldRethrowBleSetupError(error)) throw error;
|
|
1341
|
+
if (
|
|
1342
|
+
(error as { errorCode?: unknown })?.errorCode === BleErrorCode.DeviceAlreadyConnected
|
|
1343
|
+
) {
|
|
1344
|
+
// GATT resolution and the protocol probe below still validate the retained link.
|
|
1345
|
+
device = timedOutDevice;
|
|
1346
|
+
} else {
|
|
1347
|
+
remapError(error);
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1330
1350
|
}
|
|
1331
1351
|
}
|
|
1332
1352
|
if (this.stopped) throw ERRORS.TypedError(HardwareErrorCode.BleDeviceDisconnected);
|
|
@@ -2691,12 +2711,13 @@ export default class ReactNativeBleTransport {
|
|
|
2691
2711
|
/**
|
|
2692
2712
|
* A sleeping Classic drops GetFeatures/Ping and only leaves its screensaver on Initialize, which
|
|
2693
2713
|
* resets the wallet session, so it is sent once after a fully silent detection. The firmware does
|
|
2694
|
-
* not reliably answer it, so its timeout must not drop the link.
|
|
2714
|
+
* not reliably answer it, so its timeout must not drop the link. It only runs when V1 is probed
|
|
2715
|
+
* first, so a late reply lands on the V1 probe rather than on a V2 one.
|
|
2695
2716
|
*/
|
|
2696
2717
|
private async wakeSilentProtocolV1Device(uuid: string, probeOrder: ProtocolType[]) {
|
|
2697
2718
|
if (
|
|
2698
2719
|
Platform.OS !== 'android' ||
|
|
2699
|
-
|
|
2720
|
+
probeOrder[0] !== 'V1' ||
|
|
2700
2721
|
this.silentDetections.get(uuid) !== 'silent'
|
|
2701
2722
|
) {
|
|
2702
2723
|
return;
|