@onekeyfe/hd-core 1.0.36-alpha.1 → 1.0.37-alpha.3
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/api/GetPassphraseState.d.ts +1 -1
- package/dist/api/allnetwork/AllNetworkGetAddress.d.ts +3 -1
- package/dist/api/allnetwork/AllNetworkGetAddress.d.ts.map +1 -1
- package/dist/api/device/DeviceUnlock.d.ts +7 -0
- package/dist/api/device/DeviceUnlock.d.ts.map +1 -0
- package/dist/api/index.d.ts +1 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/stellar/StellarSignTransaction.d.ts.map +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/data-manager/DataManager.d.ts.map +1 -1
- package/dist/data-manager/TransportManager.d.ts.map +1 -1
- package/dist/device/Device.d.ts +9 -4
- package/dist/device/Device.d.ts.map +1 -1
- package/dist/device/DeviceCommands.d.ts +7 -5
- package/dist/device/DeviceCommands.d.ts.map +1 -1
- package/dist/events/device.d.ts +3 -0
- package/dist/events/device.d.ts.map +1 -1
- package/dist/events/ui-request.d.ts +2 -1
- package/dist/events/ui-request.d.ts.map +1 -1
- package/dist/events/ui-response.d.ts +1 -0
- package/dist/events/ui-response.d.ts.map +1 -1
- package/dist/index.d.ts +28 -11
- package/dist/index.js +213 -68
- package/dist/inject.d.ts.map +1 -1
- package/dist/types/api/deviceUnlock.d.ts +4 -0
- package/dist/types/api/deviceUnlock.d.ts.map +1 -0
- package/dist/types/api/index.d.ts +2 -0
- package/dist/types/api/index.d.ts.map +1 -1
- package/dist/types/params.d.ts +1 -0
- package/dist/types/params.d.ts.map +1 -1
- package/dist/types/settings.d.ts +1 -1
- package/dist/types/settings.d.ts.map +1 -1
- package/dist/utils/deviceFeaturesUtils.d.ts +16 -2
- package/dist/utils/deviceFeaturesUtils.d.ts.map +1 -1
- package/dist/utils/logger.d.ts +2 -0
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/patch.d.ts +1 -1
- package/dist/utils/patch.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api/FirmwareUpdate.ts +1 -1
- package/src/api/GetPassphraseState.ts +4 -4
- package/src/api/allnetwork/AllNetworkGetAddress.ts +18 -20
- package/src/api/device/DeviceUnlock.ts +26 -0
- package/src/api/firmware/FirmwareUpdateBaseMethod.ts +2 -2
- package/src/api/index.ts +1 -0
- package/src/api/stellar/StellarSignTransaction.ts +0 -3
- package/src/core/index.ts +17 -8
- package/src/data/messages/messages.json +49 -2
- package/src/data-manager/DataManager.ts +1 -1
- package/src/data-manager/TransportManager.ts +3 -0
- package/src/device/Device.ts +92 -20
- package/src/device/DeviceCommands.ts +15 -5
- package/src/events/device.ts +4 -0
- package/src/events/ui-request.ts +2 -1
- package/src/events/ui-response.ts +1 -0
- package/src/inject.ts +2 -0
- package/src/types/api/deviceUnlock.ts +4 -0
- package/src/types/api/index.ts +2 -0
- package/src/types/params.ts +5 -0
- package/src/types/settings.ts +10 -1
- package/src/utils/deviceFeaturesUtils.ts +72 -8
- package/src/utils/logger.ts +2 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { LockDevice } from '@onekeyfe/hd-transport';
|
|
2
|
+
import { ERRORS, HardwareErrorCode } from '@onekeyfe/hd-shared';
|
|
3
|
+
import { BaseMethod } from '../BaseMethod';
|
|
4
|
+
import { toHardened } from '../helpers/pathUtils';
|
|
5
|
+
|
|
6
|
+
export default class DeviceUnlock extends BaseMethod<LockDevice> {
|
|
7
|
+
init() {
|
|
8
|
+
this.useDevicePassphraseState = false;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async run() {
|
|
12
|
+
const { type } = await this.device.commands.typedCall('GetAddress', 'Address', {
|
|
13
|
+
address_n: [toHardened(44), toHardened(1), toHardened(0), 0, 0],
|
|
14
|
+
coin_name: 'Testnet',
|
|
15
|
+
script_type: 'SPENDADDRESS',
|
|
16
|
+
show_display: false,
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
// @ts-expect-error
|
|
20
|
+
if (type === 'CallMethodError') {
|
|
21
|
+
throw ERRORS.TypedError(HardwareErrorCode.RuntimeError, 'Get the passphrase state error');
|
|
22
|
+
}
|
|
23
|
+
const res = await this.device.commands.typedCall('GetFeatures', 'Features');
|
|
24
|
+
return Promise.resolve(res.message);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -306,9 +306,9 @@ export class FirmwareUpdateBaseMethod<Params> extends BaseMethod<Params> {
|
|
|
306
306
|
let progress: number;
|
|
307
307
|
if (totalSize !== undefined && processedSize !== undefined) {
|
|
308
308
|
currentFileProcessed = processedSize + chunkEnd;
|
|
309
|
-
progress = Math.min(Math.
|
|
309
|
+
progress = Math.min(Math.ceil((currentFileProcessed / totalSize) * 100), 99);
|
|
310
310
|
} else {
|
|
311
|
-
progress = Math.min(Math.
|
|
311
|
+
progress = Math.min(Math.ceil(((i + 1) / totalChunks) * 100), 99);
|
|
312
312
|
}
|
|
313
313
|
|
|
314
314
|
const writeRes = await this.emmcFileWriteWithRetry(
|
package/src/api/index.ts
CHANGED
|
@@ -27,6 +27,7 @@ export { default as deviceWipe } from './device/DeviceWipe';
|
|
|
27
27
|
export { default as deviceFullyUploadResource } from './device/DeviceFullyUploadResource';
|
|
28
28
|
export { default as deviceUpdateBootloader } from './device/DeviceUpdateBootloader';
|
|
29
29
|
export { default as deviceLock } from './device/DeviceLock';
|
|
30
|
+
export { default as deviceUnlock } from './device/DeviceUnlock';
|
|
30
31
|
export { default as deviceCancel } from './device/DeviceCancel';
|
|
31
32
|
|
|
32
33
|
export { default as setU2FCounter } from './u2f/SetU2FCounter';
|
|
@@ -194,9 +194,6 @@ export default class StellarSignTransaction extends BaseMethod<HardwareStellarSi
|
|
|
194
194
|
this.operations.push(transformed);
|
|
195
195
|
}
|
|
196
196
|
});
|
|
197
|
-
|
|
198
|
-
console.log('StellarSignTransactionParams', this.params);
|
|
199
|
-
console.log('StellarSignTransactionOperations', this.operations);
|
|
200
197
|
}
|
|
201
198
|
|
|
202
199
|
processTxRequest = async (operations: any, index: number): Promise<StellarSignedTx> => {
|
package/src/core/index.ts
CHANGED
|
@@ -342,7 +342,9 @@ const onCallDevice = async (
|
|
|
342
342
|
|
|
343
343
|
// Check Device passphrase State
|
|
344
344
|
const passphraseStateSafety = await device.checkPassphraseStateSafety(
|
|
345
|
-
method.payload?.passphraseState
|
|
345
|
+
method.payload?.passphraseState,
|
|
346
|
+
method.payload?.useEmptyPassphrase,
|
|
347
|
+
method.payload?.skipPassphraseCheck
|
|
346
348
|
);
|
|
347
349
|
|
|
348
350
|
// Double check, handles the special case of Touch/Pro
|
|
@@ -354,6 +356,9 @@ const onCallDevice = async (
|
|
|
354
356
|
ERRORS.TypedError(HardwareErrorCode.DeviceCheckPassphraseStateError)
|
|
355
357
|
);
|
|
356
358
|
}
|
|
359
|
+
|
|
360
|
+
// close pin popup window
|
|
361
|
+
postMessage(createUiMessage(UI_REQUEST.CLOSE_UI_WINDOW));
|
|
357
362
|
}
|
|
358
363
|
|
|
359
364
|
// Automatic check safety_check level for Kovan, Ropsten, Rinkeby, Goerli test networks.
|
|
@@ -774,7 +779,7 @@ const checkPassphraseEnableState = (method: BaseMethod, features?: Features) =>
|
|
|
774
779
|
if (
|
|
775
780
|
features?.passphrase_protection === true &&
|
|
776
781
|
(method.payload.passphraseState == null || method.payload.passphraseState === '') &&
|
|
777
|
-
!method.payload.useEmptyPassphrase
|
|
782
|
+
(!method.payload.useEmptyPassphrase || !method.payload.skipPassphraseCheck)
|
|
778
783
|
) {
|
|
779
784
|
DevicePool.clearDeviceCache(method.payload.connectId);
|
|
780
785
|
throw ERRORS.TypedError(HardwareErrorCode.DeviceOpenedPassphrase);
|
|
@@ -836,12 +841,12 @@ const onDevicePinHandler = async (...[device, type, callback]: DeviceEvents['pin
|
|
|
836
841
|
const onDeviceButtonHandler = (...[device, request]: [...DeviceEvents['button']]) => {
|
|
837
842
|
postMessage(createDeviceMessage(DEVICE.BUTTON, { ...request, device: device.toMessageObject() }));
|
|
838
843
|
|
|
839
|
-
if (request.code === 'ButtonRequest_PinEntry') {
|
|
840
|
-
Log.log('request Confirm Input PIN');
|
|
844
|
+
if (request.code === 'ButtonRequest_PinEntry' || request.code === 'ButtonRequest_AttachPin') {
|
|
845
|
+
Log.log('request Confirm Input PIN or Attach PIN');
|
|
841
846
|
postMessage(
|
|
842
847
|
createUiMessage(UI_REQUEST.REQUEST_PIN, {
|
|
843
848
|
device: device.toMessageObject() as KnownDevice,
|
|
844
|
-
type:
|
|
849
|
+
type: request.code,
|
|
845
850
|
})
|
|
846
851
|
);
|
|
847
852
|
} else {
|
|
@@ -854,27 +859,31 @@ const onDeviceFeaturesHandler = (...[_, features]: [...DeviceEvents['features']]
|
|
|
854
859
|
postMessage(createDeviceMessage(DEVICE.FEATURES, { ...features }));
|
|
855
860
|
};
|
|
856
861
|
|
|
857
|
-
const onDevicePassphraseHandler = async (
|
|
862
|
+
const onDevicePassphraseHandler = async (
|
|
863
|
+
...[device, requestPayload, callback]: DeviceEvents['passphrase']
|
|
864
|
+
) => {
|
|
858
865
|
Log.debug('onDevicePassphraseHandler');
|
|
859
866
|
const uiPromise = createUiPromise(UI_RESPONSE.RECEIVE_PASSPHRASE, device);
|
|
860
867
|
postMessage(
|
|
861
868
|
createUiMessage(UI_REQUEST.REQUEST_PASSPHRASE, {
|
|
862
869
|
device: device.toMessageObject() as KnownDevice,
|
|
863
870
|
passphraseState: device.passphraseState,
|
|
871
|
+
existsAttachPinUser: requestPayload.existsAttachPinUser,
|
|
864
872
|
})
|
|
865
873
|
);
|
|
866
874
|
// wait for passphrase
|
|
867
875
|
const uiResp = await uiPromise.promise;
|
|
868
|
-
const { value, passphraseOnDevice, save } = uiResp.payload;
|
|
876
|
+
const { value, passphraseOnDevice, save, attachPinOnDevice } = uiResp.payload;
|
|
869
877
|
// send as PassphrasePromptResponse
|
|
870
878
|
callback({
|
|
871
879
|
passphrase: value.normalize('NFKD'),
|
|
872
880
|
passphraseOnDevice,
|
|
881
|
+
attachPinOnDevice,
|
|
873
882
|
cache: save,
|
|
874
883
|
});
|
|
875
884
|
};
|
|
876
885
|
|
|
877
|
-
const onEmptyPassphraseHandler = (...[_, callback]: DeviceEvents['passphrase']) => {
|
|
886
|
+
const onEmptyPassphraseHandler = (...[_, , callback]: DeviceEvents['passphrase']) => {
|
|
878
887
|
Log.debug('onEmptyPassphraseHandler');
|
|
879
888
|
// send as PassphrasePromptResponse
|
|
880
889
|
callback({ passphrase: '' });
|
|
@@ -3021,7 +3021,8 @@
|
|
|
3021
3021
|
"ButtonRequest_Success": 17,
|
|
3022
3022
|
"ButtonRequest_Warning": 18,
|
|
3023
3023
|
"ButtonRequest_PassphraseEntry": 19,
|
|
3024
|
-
"ButtonRequest_PinEntry": 20
|
|
3024
|
+
"ButtonRequest_PinEntry": 20,
|
|
3025
|
+
"ButtonRequest_AttachPin": 8000
|
|
3025
3026
|
}
|
|
3026
3027
|
}
|
|
3027
3028
|
}
|
|
@@ -3071,6 +3072,10 @@
|
|
|
3071
3072
|
"options": {
|
|
3072
3073
|
"deprecated": true
|
|
3073
3074
|
}
|
|
3075
|
+
},
|
|
3076
|
+
"exists_attach_pin_user": {
|
|
3077
|
+
"type": "bool",
|
|
3078
|
+
"id": 8000
|
|
3074
3079
|
}
|
|
3075
3080
|
}
|
|
3076
3081
|
},
|
|
@@ -3090,6 +3095,10 @@
|
|
|
3090
3095
|
"on_device": {
|
|
3091
3096
|
"type": "bool",
|
|
3092
3097
|
"id": 3
|
|
3098
|
+
},
|
|
3099
|
+
"on_device_attach_pin": {
|
|
3100
|
+
"type": "bool",
|
|
3101
|
+
"id": 8000
|
|
3093
3102
|
}
|
|
3094
3103
|
}
|
|
3095
3104
|
},
|
|
@@ -6051,6 +6060,10 @@
|
|
|
6051
6060
|
"derive_cardano": {
|
|
6052
6061
|
"type": "bool",
|
|
6053
6062
|
"id": 3
|
|
6063
|
+
},
|
|
6064
|
+
"passphrase_state": {
|
|
6065
|
+
"type": "string",
|
|
6066
|
+
"id": 8000
|
|
6054
6067
|
}
|
|
6055
6068
|
}
|
|
6056
6069
|
},
|
|
@@ -6429,6 +6442,14 @@
|
|
|
6429
6442
|
"onekey_se04_state": {
|
|
6430
6443
|
"type": "OneKeySEState",
|
|
6431
6444
|
"id": 624
|
|
6445
|
+
},
|
|
6446
|
+
"attach_to_pin_user": {
|
|
6447
|
+
"type": "bool",
|
|
6448
|
+
"id": 625
|
|
6449
|
+
},
|
|
6450
|
+
"unlocked_attach_pin": {
|
|
6451
|
+
"type": "bool",
|
|
6452
|
+
"id": 626
|
|
6432
6453
|
}
|
|
6433
6454
|
},
|
|
6434
6455
|
"nested": {
|
|
@@ -7533,6 +7554,30 @@
|
|
|
7533
7554
|
}
|
|
7534
7555
|
}
|
|
7535
7556
|
},
|
|
7557
|
+
"GetPassphraseState": {
|
|
7558
|
+
"fields": {
|
|
7559
|
+
"passphrase_state": {
|
|
7560
|
+
"type": "string",
|
|
7561
|
+
"id": 1
|
|
7562
|
+
}
|
|
7563
|
+
}
|
|
7564
|
+
},
|
|
7565
|
+
"PassphraseState": {
|
|
7566
|
+
"fields": {
|
|
7567
|
+
"passphrase_state": {
|
|
7568
|
+
"type": "string",
|
|
7569
|
+
"id": 1
|
|
7570
|
+
},
|
|
7571
|
+
"session_id": {
|
|
7572
|
+
"type": "bytes",
|
|
7573
|
+
"id": 2
|
|
7574
|
+
},
|
|
7575
|
+
"unlocked_attach_pin": {
|
|
7576
|
+
"type": "bool",
|
|
7577
|
+
"id": 3
|
|
7578
|
+
}
|
|
7579
|
+
}
|
|
7580
|
+
},
|
|
7536
7581
|
"MoneroTransactionSourceEntry": {
|
|
7537
7582
|
"fields": {
|
|
7538
7583
|
"outputs": {
|
|
@@ -12144,7 +12189,9 @@
|
|
|
12144
12189
|
"MessageType_ListResDir": 10023,
|
|
12145
12190
|
"MessageType_FileInfoList": 10024,
|
|
12146
12191
|
"MessageType_OnekeyGetFeatures": 10025,
|
|
12147
|
-
"MessageType_OnekeyFeatures": 10026
|
|
12192
|
+
"MessageType_OnekeyFeatures": 10026,
|
|
12193
|
+
"MessageType_GetPassphraseState": 10028,
|
|
12194
|
+
"MessageType_PassphraseState": 10029
|
|
12148
12195
|
}
|
|
12149
12196
|
},
|
|
12150
12197
|
"google": {
|
|
@@ -349,7 +349,7 @@ export default class DataManager {
|
|
|
349
349
|
}
|
|
350
350
|
|
|
351
351
|
static isBleConnect = (env: ConnectSettings['env']) =>
|
|
352
|
-
env === 'react-native' || env === 'lowlevel';
|
|
352
|
+
env === 'react-native' || env === 'lowlevel' || env === 'desktop-web-ble';
|
|
353
353
|
|
|
354
354
|
static isWebUsbConnect = (env: ConnectSettings['env']) => env === 'webusb';
|
|
355
355
|
}
|
|
@@ -11,6 +11,7 @@ const Log = getLogger(LoggerNames.Transport);
|
|
|
11
11
|
const BleLogger = getLogger(LoggerNames.HdBleTransport);
|
|
12
12
|
const HttpLogger = getLogger(LoggerNames.HdTransportHttp);
|
|
13
13
|
const LowLevelLogger = getLogger(LoggerNames.HdTransportLowLevel);
|
|
14
|
+
const WebBleLogger = getLogger(LoggerNames.HdWebBleTransport);
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* transport 在同一个环境中只会存在一个
|
|
@@ -56,6 +57,8 @@ export default class TransportManager {
|
|
|
56
57
|
);
|
|
57
58
|
}
|
|
58
59
|
await this.transport.init(LowLevelLogger, DevicePool.emitter, this.plugin);
|
|
60
|
+
} else if (env === 'desktop-web-ble') {
|
|
61
|
+
await this.transport.init(WebBleLogger);
|
|
59
62
|
} else {
|
|
60
63
|
await this.transport.init(HttpLogger);
|
|
61
64
|
}
|
package/src/device/Device.ts
CHANGED
|
@@ -33,7 +33,13 @@ import {
|
|
|
33
33
|
type Features,
|
|
34
34
|
type UnavailableCapabilities,
|
|
35
35
|
} from '../types';
|
|
36
|
-
import {
|
|
36
|
+
import {
|
|
37
|
+
DEVICE,
|
|
38
|
+
DeviceButtonRequestPayload,
|
|
39
|
+
DeviceFeaturesPayload,
|
|
40
|
+
PassphraseRequestPayload,
|
|
41
|
+
UI_REQUEST,
|
|
42
|
+
} from '../events';
|
|
37
43
|
import { PROTO } from '../constants';
|
|
38
44
|
import { DataManager } from '../data-manager';
|
|
39
45
|
import TransportManager from '../data-manager/TransportManager';
|
|
@@ -61,7 +67,11 @@ export interface DeviceEvents {
|
|
|
61
67
|
[DEVICE.PASSPHRASE_ON_DEVICE]: [Device, ((response: any) => void)?];
|
|
62
68
|
[DEVICE.BUTTON]: [Device, DeviceButtonRequestPayload];
|
|
63
69
|
[DEVICE.FEATURES]: [Device, DeviceFeaturesPayload];
|
|
64
|
-
[DEVICE.PASSPHRASE]: [
|
|
70
|
+
[DEVICE.PASSPHRASE]: [
|
|
71
|
+
Device,
|
|
72
|
+
PassphraseRequestPayload,
|
|
73
|
+
(response: PassphrasePromptResponse, error?: Error) => void
|
|
74
|
+
];
|
|
65
75
|
[DEVICE.SELECT_DEVICE_IN_BOOTLOADER_FOR_WEB_DEVICE]: [
|
|
66
76
|
Device,
|
|
67
77
|
(err: any, deviceId: string) => void
|
|
@@ -288,13 +298,13 @@ export class Device extends EventEmitter {
|
|
|
288
298
|
}
|
|
289
299
|
|
|
290
300
|
getInternalState(_deviceId?: string) {
|
|
301
|
+
Log.debug('getInternalState session cache: ', deviceSessionCache);
|
|
291
302
|
Log.debug(
|
|
292
303
|
'getInternalState session param: ',
|
|
293
304
|
`device_id: ${_deviceId}`,
|
|
294
305
|
`features.device_id: ${this.features?.device_id}`,
|
|
295
306
|
`passphraseState: ${this.passphraseState}`
|
|
296
307
|
);
|
|
297
|
-
Log.debug('getInternalState session cache: ', deviceSessionCache);
|
|
298
308
|
|
|
299
309
|
const deviceId = _deviceId || this.features?.device_id;
|
|
300
310
|
if (!deviceId) return undefined;
|
|
@@ -304,23 +314,39 @@ export class Device extends EventEmitter {
|
|
|
304
314
|
return deviceSessionCache[usePassKey];
|
|
305
315
|
}
|
|
306
316
|
|
|
307
|
-
|
|
317
|
+
// attach to pin to fix internal state
|
|
318
|
+
updateInternalState(
|
|
319
|
+
enablePassphrase: boolean,
|
|
320
|
+
passphraseState: string | undefined,
|
|
321
|
+
deviceId: string,
|
|
322
|
+
sessionId: string | null = null,
|
|
323
|
+
featuresSessionId: string | null = null
|
|
324
|
+
) {
|
|
308
325
|
Log.debug(
|
|
309
|
-
'
|
|
326
|
+
'updateInternalState session param: ',
|
|
310
327
|
`device_id: ${deviceId}`,
|
|
311
|
-
`
|
|
312
|
-
`
|
|
328
|
+
`enablePassphrase: ${enablePassphrase}`,
|
|
329
|
+
`passphraseState: ${passphraseState}`,
|
|
330
|
+
`sessionId: ${sessionId}`,
|
|
331
|
+
`featuresSessionId: ${featuresSessionId}`
|
|
313
332
|
);
|
|
314
333
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
334
|
+
if (enablePassphrase) {
|
|
335
|
+
// update the sessionId
|
|
336
|
+
if (sessionId) {
|
|
337
|
+
deviceSessionCache[this.generateStateKey(deviceId, passphraseState)] = sessionId;
|
|
338
|
+
} else if (featuresSessionId) {
|
|
339
|
+
deviceSessionCache[this.generateStateKey(deviceId, passphraseState)] = featuresSessionId;
|
|
340
|
+
}
|
|
322
341
|
}
|
|
323
|
-
|
|
342
|
+
|
|
343
|
+
// delete the old sessionId
|
|
344
|
+
const oldKey = `${deviceId}`;
|
|
345
|
+
if (deviceSessionCache[oldKey]) {
|
|
346
|
+
delete deviceSessionCache[oldKey];
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
Log.debug('updateInternalState session cache: ', deviceSessionCache);
|
|
324
350
|
}
|
|
325
351
|
|
|
326
352
|
private setInternalState(state: string, initSession?: boolean) {
|
|
@@ -361,7 +387,7 @@ export class Device extends EventEmitter {
|
|
|
361
387
|
}
|
|
362
388
|
|
|
363
389
|
async initialize(options?: InitOptions) {
|
|
364
|
-
Log.debug('initialize param:', options);
|
|
390
|
+
// Log.debug('initialize param:', options);
|
|
365
391
|
|
|
366
392
|
this.passphraseState = options?.passphraseState;
|
|
367
393
|
|
|
@@ -378,8 +404,14 @@ export class Device extends EventEmitter {
|
|
|
378
404
|
if (options?.deriveCardano) {
|
|
379
405
|
payload.derive_cardano = true;
|
|
380
406
|
}
|
|
407
|
+
payload.passphrase_state = options?.passphraseState;
|
|
381
408
|
|
|
382
|
-
Log.debug('
|
|
409
|
+
Log.debug('Initialize device begin:', {
|
|
410
|
+
deviceId: options?.deviceId,
|
|
411
|
+
passphraseState: options?.passphraseState,
|
|
412
|
+
initSession: options?.initSession,
|
|
413
|
+
InitializePayload: payload,
|
|
414
|
+
});
|
|
383
415
|
|
|
384
416
|
try {
|
|
385
417
|
// @ts-expect-error
|
|
@@ -393,6 +425,7 @@ export class Device extends EventEmitter {
|
|
|
393
425
|
}),
|
|
394
426
|
]);
|
|
395
427
|
|
|
428
|
+
Log.debug('Initialize device end: ', message);
|
|
396
429
|
this._updateFeatures(message, options?.initSession);
|
|
397
430
|
await TransportManager.reconfigure(this.features);
|
|
398
431
|
} catch (error) {
|
|
@@ -693,12 +726,51 @@ export class Device extends EventEmitter {
|
|
|
693
726
|
return false;
|
|
694
727
|
}
|
|
695
728
|
|
|
696
|
-
async
|
|
729
|
+
async lockDevice() {
|
|
730
|
+
const res = await this.commands.typedCall('LockDevice', 'Success', {});
|
|
731
|
+
return res.message;
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
async checkPassphraseStateSafety(
|
|
735
|
+
passphraseState?: string,
|
|
736
|
+
useEmptyPassphraseState?: boolean,
|
|
737
|
+
skipPassphraseCheck?: boolean
|
|
738
|
+
) {
|
|
697
739
|
if (!this.features) return false;
|
|
698
|
-
const
|
|
740
|
+
const { passphraseState: newPassphraseState, unlockedAttachPin } =
|
|
741
|
+
await getPassphraseStateWithRefreshDeviceInfo(this, {
|
|
742
|
+
expectPassphraseState: passphraseState,
|
|
743
|
+
onlyMainPin: useEmptyPassphraseState,
|
|
744
|
+
});
|
|
745
|
+
|
|
746
|
+
if (skipPassphraseCheck) {
|
|
747
|
+
return true;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
// Main wallet and unlock Attach Pin, throw safe error
|
|
751
|
+
const mainWalletUseAttachPin = unlockedAttachPin && useEmptyPassphraseState;
|
|
752
|
+
const useErrorAttachPin =
|
|
753
|
+
unlockedAttachPin && passphraseState && passphraseState !== newPassphraseState;
|
|
754
|
+
|
|
755
|
+
Log.debug('Check passphrase state safety: ', {
|
|
756
|
+
passphraseState,
|
|
757
|
+
newPassphraseState,
|
|
758
|
+
unlockedAttachPin,
|
|
759
|
+
useEmptyPassphraseState,
|
|
760
|
+
});
|
|
761
|
+
|
|
762
|
+
if (mainWalletUseAttachPin || useErrorAttachPin) {
|
|
763
|
+
try {
|
|
764
|
+
await this.lockDevice();
|
|
765
|
+
} catch (error) {
|
|
766
|
+
// ignore error
|
|
767
|
+
}
|
|
768
|
+
this.clearInternalState();
|
|
769
|
+
return Promise.reject(ERRORS.TypedError(HardwareErrorCode.DeviceCheckUnlockTypeError));
|
|
770
|
+
}
|
|
699
771
|
|
|
700
772
|
// When exists passphraseState, check passphraseState
|
|
701
|
-
if (passphraseState && passphraseState !==
|
|
773
|
+
if (passphraseState && passphraseState !== newPassphraseState) {
|
|
702
774
|
this.clearInternalState();
|
|
703
775
|
return false;
|
|
704
776
|
}
|
|
@@ -4,12 +4,13 @@ import TransportManager from '../data-manager/TransportManager';
|
|
|
4
4
|
import DataManager from '../data-manager/DataManager';
|
|
5
5
|
import { patchFeatures, getLogger, LoggerNames, getDeviceType } from '../utils';
|
|
6
6
|
import type { Device } from './Device';
|
|
7
|
-
import { DEVICE } from '../events';
|
|
7
|
+
import { DEVICE, type PassphraseRequestPayload } from '../events';
|
|
8
8
|
import { DeviceModelToTypes } from '../types';
|
|
9
9
|
|
|
10
10
|
export type PassphrasePromptResponse = {
|
|
11
11
|
passphrase?: string;
|
|
12
12
|
passphraseOnDevice?: boolean;
|
|
13
|
+
attachPinOnDevice?: boolean;
|
|
13
14
|
cache?: boolean;
|
|
14
15
|
};
|
|
15
16
|
|
|
@@ -217,7 +218,6 @@ export class DeviceCommands {
|
|
|
217
218
|
this.callPromise = promise;
|
|
218
219
|
const res = await promise;
|
|
219
220
|
Log.debug('[DeviceCommands] [call] Received', res.type);
|
|
220
|
-
console.log('[DeviceCommands] [call] Received', res.type);
|
|
221
221
|
return res;
|
|
222
222
|
} catch (error) {
|
|
223
223
|
Log.debug('[DeviceCommands] [call] Received error', error);
|
|
@@ -438,8 +438,17 @@ export class DeviceCommands {
|
|
|
438
438
|
}
|
|
439
439
|
|
|
440
440
|
if (res.type === 'PassphraseRequest') {
|
|
441
|
-
|
|
442
|
-
|
|
441
|
+
const existsAttachPinUser = res.message.exists_attach_pin_user;
|
|
442
|
+
return this._promptPassphrase({
|
|
443
|
+
existsAttachPinUser,
|
|
444
|
+
}).then(response => {
|
|
445
|
+
const { passphrase, passphraseOnDevice, attachPinOnDevice } = response;
|
|
446
|
+
|
|
447
|
+
// Attach PIN on device
|
|
448
|
+
if (attachPinOnDevice && existsAttachPinUser) {
|
|
449
|
+
return this._commonCall('PassphraseAck', { on_device_attach_pin: true });
|
|
450
|
+
}
|
|
451
|
+
|
|
443
452
|
return !passphraseOnDevice
|
|
444
453
|
? this._commonCall('PassphraseAck', { passphrase })
|
|
445
454
|
: this._commonCall('PassphraseAck', { on_device: true });
|
|
@@ -501,7 +510,7 @@ export class DeviceCommands {
|
|
|
501
510
|
});
|
|
502
511
|
}
|
|
503
512
|
|
|
504
|
-
_promptPassphrase() {
|
|
513
|
+
_promptPassphrase(options: PassphraseRequestPayload) {
|
|
505
514
|
return new Promise<PassphrasePromptResponse>((resolve, reject) => {
|
|
506
515
|
const cancelAndReject = (_error?: Error) =>
|
|
507
516
|
cancelDeviceInPrompt(this.device, false)
|
|
@@ -527,6 +536,7 @@ export class DeviceCommands {
|
|
|
527
536
|
this.device.emit(
|
|
528
537
|
DEVICE.PASSPHRASE,
|
|
529
538
|
this.device,
|
|
539
|
+
options,
|
|
530
540
|
(response: PassphrasePromptResponse, error?: Error) => {
|
|
531
541
|
this.device.clearCancelableAction();
|
|
532
542
|
if (error) {
|
package/src/events/device.ts
CHANGED
|
@@ -44,6 +44,10 @@ export interface DeviceButtonRequestPayload extends Omit<PROTO.ButtonRequest, 'c
|
|
|
44
44
|
code?: PROTO.ButtonRequest['code'] | 'ButtonRequest_FirmwareUpdate';
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
export type PassphraseRequestPayload = {
|
|
48
|
+
existsAttachPinUser?: boolean;
|
|
49
|
+
};
|
|
50
|
+
|
|
47
51
|
export interface DeviceButtonRequest {
|
|
48
52
|
type: typeof DEVICE.BUTTON;
|
|
49
53
|
payload: DeviceButtonRequestPayload & { device: Device | null };
|
package/src/events/ui-request.ts
CHANGED
|
@@ -66,7 +66,7 @@ export type UiRequestDeviceAction = {
|
|
|
66
66
|
type: typeof UI_REQUEST.REQUEST_PIN;
|
|
67
67
|
payload: {
|
|
68
68
|
device: Device;
|
|
69
|
-
type?: PROTO.PinMatrixRequestType | 'ButtonRequest_PinEntry';
|
|
69
|
+
type?: PROTO.PinMatrixRequestType | 'ButtonRequest_PinEntry' | 'ButtonRequest_AttachPin';
|
|
70
70
|
};
|
|
71
71
|
};
|
|
72
72
|
|
|
@@ -80,6 +80,7 @@ export interface UiRequestPassphrase {
|
|
|
80
80
|
payload: {
|
|
81
81
|
device: Device;
|
|
82
82
|
passphraseState?: string;
|
|
83
|
+
existsAttachPinUser?: boolean;
|
|
83
84
|
};
|
|
84
85
|
}
|
|
85
86
|
|
package/src/inject.ts
CHANGED
|
@@ -138,6 +138,8 @@ export const createCoreApi = (
|
|
|
138
138
|
call({ ...params, connectId, method: 'getPassphraseState' }),
|
|
139
139
|
deviceCancel: (connectId, params) => call({ ...params, connectId, method: 'deviceCancel' }),
|
|
140
140
|
deviceLock: (connectId, params) => call({ ...params, connectId, method: 'deviceLock' }),
|
|
141
|
+
deviceUnlock: (connectId, params) =>
|
|
142
|
+
call({ ...params, useEmptyPassphrase: true, connectId, method: 'deviceUnlock' }),
|
|
141
143
|
|
|
142
144
|
getNextU2FCounter: (connectId, params) =>
|
|
143
145
|
call({ ...params, connectId, method: 'getNextU2FCounter' }),
|
package/src/types/api/index.ts
CHANGED
|
@@ -35,6 +35,7 @@ import { deviceSupportFeatures } from './deviceSupportFeatures';
|
|
|
35
35
|
import { deviceFullyUploadResource } from './deviceFullyUploadResource';
|
|
36
36
|
import { deviceUpdateBootloader } from './deviceUpdateBootloader';
|
|
37
37
|
import { deviceLock } from './deviceLock';
|
|
38
|
+
import { deviceUnlock } from './deviceUnlock';
|
|
38
39
|
import { deviceCancel } from './deviceCancel';
|
|
39
40
|
|
|
40
41
|
import { getNextU2FCounter } from './getNextU2FCounter';
|
|
@@ -214,6 +215,7 @@ export type CoreApi = {
|
|
|
214
215
|
deviceFullyUploadResource: typeof deviceFullyUploadResource;
|
|
215
216
|
deviceUpdateBootloader: typeof deviceUpdateBootloader;
|
|
216
217
|
deviceLock: typeof deviceLock;
|
|
218
|
+
deviceUnlock: typeof deviceUnlock;
|
|
217
219
|
deviceCancel: typeof deviceCancel;
|
|
218
220
|
getNextU2FCounter: typeof getNextU2FCounter;
|
|
219
221
|
setU2FCounter: typeof setU2FCounter;
|
package/src/types/params.ts
CHANGED
|
@@ -37,6 +37,11 @@ export interface CommonParams {
|
|
|
37
37
|
* Skip web device prompt
|
|
38
38
|
*/
|
|
39
39
|
skipWebDevicePrompt?: boolean;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Skip passphrase check
|
|
43
|
+
*/
|
|
44
|
+
skipPassphraseCheck?: boolean;
|
|
40
45
|
}
|
|
41
46
|
|
|
42
47
|
export type Params<T> = CommonParams & T & { bundle?: undefined };
|
package/src/types/settings.ts
CHANGED
|
@@ -14,7 +14,16 @@ export type ConnectSettings = {
|
|
|
14
14
|
priority: number;
|
|
15
15
|
trustedHost: boolean;
|
|
16
16
|
supportedBrowser?: boolean;
|
|
17
|
-
env:
|
|
17
|
+
env:
|
|
18
|
+
| 'node'
|
|
19
|
+
| 'web'
|
|
20
|
+
| 'webextension'
|
|
21
|
+
| 'electron'
|
|
22
|
+
| 'react-native'
|
|
23
|
+
| 'webusb'
|
|
24
|
+
| 'emulator'
|
|
25
|
+
| 'desktop-web-ble'
|
|
26
|
+
| 'lowlevel';
|
|
18
27
|
timestamp: number;
|
|
19
28
|
isFrame?: boolean;
|
|
20
29
|
preRelease?: boolean;
|